Foundation — FileManager

FileManager 的简介 #

FileManager 是 iOS 和 macOS 开发中提供的一个强大的类,用于管理文件系统的操作。它提供了对文件和文件夹进行创建、删除、移动、复制以及检索其属性等多种功能的接口。

FileManagerFoundation 框架的一部分,是 用户文件系统交互的核心工具


1. FileManager 的体系结构 #

FileManager 由以下几个部分组成:

模块功能描述
文件操作功能创建、删除、移动、复制文件和目录。
文件路径解析检索、拼接和解析文件路径,例如获取用户的文档目录或临时目录。
文件属性管理获取文件属性,例如大小、创建时间、权限等。
文件存在检查检查文件或文件夹是否存在。
枚举和搜索枚举目录内容,递归浏览文件系统内容,或者根据条件搜索文件和文件夹。
文件权限检查权限信息,以及管理可读、可写、可执行属性。

关键方法和属性 #

以下是 FileManager 的几个核心方法和属性:

以下是对 FileManager 的接口按功能分类的详细整理,包括方法名称以及对应的中文说明。分类基于 FileManager 的主要功能模块,包括文件操作、目录操作、文件系统信息、枚举和遍历操作等。

1. 文件操作

  • 创建、删除、复制、移动文件及文件夹的基础管理。

2. 目录操作

  • 创建文件夹、列举内容、获取子路径等。

3. 文件检查

  • 检测文件是否存在,以及文件基本操作权限。

4. 文件属性

  • 获取文件的大小、日期、权限等属性,或者设置某些属性。

5. 沙盒路径

  • 获取用户目录、文档目录、缓存目录、临时路径等。

6. 数据写入与读取

  • 管理文件的内容。

7. 遍历和枚举

  • 遍历文件与子目录,递归或非递归模型支持。

1. 文件操作接口 #

方法名称中文说明
createFile(atPath:contents:attributes:)创建文件并写入数据。可以指定文件的路径、内容和属性。
removeItem(at:)删除指定路径的文件或文件夹。
copyItem(at:to:)复制文件或文件夹到目标路径。
moveItem(at:to:)移动或重命名文件或文件夹。
linkItem(at:to:)创建指定路径的硬链接。
contents(atPath:)读取文件的二进制数据内容。
contentsEqual(atPath:andPath:)比较两个文件是否完全相同。
replaceItem(at:withItemAt:backupItemName:options:)替换文件,可以选择备份原来的文件并指定备份文件的名称。

2. 目录操作接口 #

方法名称中文说明
createDirectory(at:withIntermediateDirectories:attributes:)创建一个新的目录,可以选择创建中间缺少的目录。
contentsOfDirectory(at:includingPropertiesForKeys:options:)获取指定目录中内容(如文件和子目录),包含属性信息。
subpathsOfDirectory(atPath:)获取指定路径的所有子路径(递归)。
enumerator(at:includingPropertiesForKeys:options:errorHandler:)枚举目录内容,包括文件和子目录。
changeCurrentDirectoryPath(_: String)更改当前工作目录路径。
displayName(atPath:)返回指定路径的友好显示名称。

3. 文件检查和验证接口 #

方法名称中文说明
fileExists(atPath:)检查指定的路径是否存在文件或目录。
isReadableFile(atPath:)检查路径是否可读取。
isWritableFile(atPath:)检查路径是否可写入。
isExecutableFile(atPath:)检查路径是否可执行。
isDeletableFile(atPath:)检查路径是否可以删除。

4. 文件系统属性接口 #

方法名称中文说明
attributesOfItem(atPath:)获取指定路径的文件或目录属性(如大小、创建时间)。
attributesOfFileSystem(forPath:)获取指定文件系统的属性(如可用空间、文件系统类型)。
setAttributes(_:ofItemAtPath:)设置文件或目录的属性,例如修改权限或修改时间戳。

5. 常见的沙盒和目录路径接口 #

方法名称中文说明
urls(for:in:)获取指定目录(如文档目录、缓存目录)的 URL。
temporaryDirectory获取系统的临时目录路径。
homeDirectoryForCurrentUser获取当前用户的主目录路径(仅 macOS 支持)。
homeDirectoryForGuest()获取访客用户的主目录路径(仅 macOS 支持)。
currentDirectoryPath获取或更改当前工作目录路径。

6. 数据读取与写入接口 #

方法名称中文说明
contents(atPath:)从文件路径读取内容并返回 Data 类型的二进制数据。
createFile(atPath:contents:attributes:)在指定路径上创建文件并写入内容。
removeItem(at:)删除文件或目录。

7. 目录遍历和枚举接口 #

方法名称中文说明
contentsOfDirectory(atPath:)返回指定路径的文件和子目录,不递归。
subpathsOfDirectory(atPath:)获取指定目录中所有内容(递归,包括文件夹和文件)。
enumerator(at:includingPropertiesForKeys:options:errorHandler:)创建目录枚举器,递归遍历目录中的文件和子目录。

8. 符号链接和硬链接操作接口 #

方法名称中文说明
linkItem(at:to:)在指定路径创建硬链接。
destinationOfSymbolicLink(atPath:)返回符号链接指向的真实路径(读取符号链接的目标路径)。

9. 数据迁移与备份接口 #

方法名称中文说明
replaceItem(at:withItemAt:backupItemName:options:)替换指定路径的文件,并可选择为原文件创建备份。

10. iCloud 文件操作接口 #

方法名称中文说明
url(forUbiquityContainerIdentifier:)获取 iCloud 容器目录的 URL(如果启用了 iCloud)。
isUbiquitousItem(at:)检查是否是 iCloud 文件。

11. 可用 iOS/macOS 的属性与共享组接口 #

方法名称中文说明
containerURL(forSecurityApplicationGroupIdentifier:)获取 App Group 共享目录,用于跨应用共享文件。

注意事项 #

以下为 FileManager 使用中的开发者常见注意点:

  1. 沙盒环境限制

    • iOS 应用运行在沙盒环境下,开发者只能访问自己应用的沙盒目录,比如 DocumentsLibraryCaches 等。
    • 无法访问其他应用的目录或系统级目录。
  2. 文件操作权限

    • 在创建目录或文件时,需要检查操作权限是否满足,尤其在 macOS 上,如果涉及全局目录(例如 /Library),需要管理员权限。
  3. 错误处理

    • 几乎所有 FileManager 方法都可能抛出错误(如路径不存在、权限问题等),因此建议在操作文件时使用 do-catch 语句来捕获错误。
  4. 数据安全性

    • 在存储敏感数据时,应确保文件和路径具备适当的权限控制(如 NSFileProtectionComplete)。
  5. 跨平台适用性

    • 部分方法(例如 homeDirectoryForCurrentUserisUbiquitousItem(at:))仅适用于 macOS 或在启用了特定功能(如 iCloud)后才可用。

2. 使用 FileManager 的步骤 #

2.1 获取 FileManager 的共享实例 #

FileManager 是一个共享实例类,通过其 default 属性可以获取实例。

let fileManager = FileManager.default

通过此实例可以执行各种文件操作。


2.2 获取常见的沙盒路径 #

iOS 和 macOS 应用运行在一个 沙盒环境 中,无法直接访问系统文件。常见的沙盒目录包括:

目录类型描述
Documents用户可见的数据目录,用于持久化保存用户文件。
Caches用于存储缓存文件,可被系统随时清理。
Temporary临时目录,系统可能会随时清理。用于存储临时文件。

示例代码:获取常见目录 #

let fileManager = FileManager.default

// 获取文档目录路径
if let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first {
    print("Documents Directory: \(documentsDirectory)")
}

// 获取缓存目录路径
if let cachesDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first {
    print("Caches Directory: \(cachesDirectory)")
}

// 获取临时目录路径
let tempDirectory = fileManager.temporaryDirectory
print("Temporary Directory: \(tempDirectory)")

2.3 创建文件夹 #

示例代码: #

let fileManager = FileManager.default

// 创建自定义文件夹(路径为沙盒内 Documents 文件夹下)
if let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first {
    let newFolderURL = documentsDirectory.appendingPathComponent("NewFolder")
    
    do {
        try fileManager.createDirectory(at: newFolderURL, withIntermediateDirectories: true, attributes: nil)
        print("Folder created at: \(newFolderURL)")
    } catch {
        print("Failed to create folder: \(error.localizedDescription)")
    }
}

2.4 检查文件是否存在 #

示例代码: #

let filePath = "/path/to/your/file.txt"
if fileManager.fileExists(atPath: filePath) {
    print("File exists.")
} else {
    print("File does not exist.")
}

2.5 文件的存储与读取 #

1. 写入文本文件 #

if let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first {
    let fileURL = documentsDirectory.appendingPathComponent("example.txt")
    let data = "Hello, FileManager!".data(using: .utf8)
    
    // 创建文件
    fileManager.createFile(atPath: fileURL.path, contents: data, attributes: nil)
    print("File created: \(fileURL)")
}

2. 读取文件数据 #

if let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first {
    let fileURL = documentsDirectory.appendingPathComponent("example.txt")
    
    if let fileData = fileManager.contents(atPath: fileURL.path),
       let fileContent = String(data: fileData, encoding: .utf8) {
        print("File content: \(fileContent)")
    }
}

2.6 移动文件或重命名 #

示例代码: #

if let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first {
    let sourceURL = documentsDirectory.appendingPathComponent("example.txt")
    let destinationURL = documentsDirectory.appendingPathComponent("renamed_example.txt")
    
    do {
        try fileManager.moveItem(at: sourceURL, to: destinationURL)
        print("File moved/renamed to: \(destinationURL)")
    } catch {
        print("Failed to move file: \(error.localizedDescription)")
    }
}

2.7 删除文件或文件夹 #

示例代码: #

if let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first {
    let fileURL = documentsDirectory.appendingPathComponent("example.txt")
    
    do {
        try fileManager.removeItem(at: fileURL)
        print("File deleted: \(fileURL)")
    } catch {
        print("Failed to delete file: \(error.localizedDescription)")
    }
}

2.8 获取文件属性 #

你可以通过 attributesOfItem(atPath:) 方法检索文件的详细属性(如创建时间、文件大小等)。

示例代码: #

if let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first {
    let fileURL = documentsDirectory.appendingPathComponent("example.txt")
    
    do {
        let attributes = try fileManager.attributesOfItem(atPath: fileURL.path)
        print("File attributes: \(attributes)")
        
        if let fileSize = attributes[.size] as? Int64 {
            print("File size: \(fileSize) bytes")
        }
    } catch {
        print("Failed to get file attributes: \(error.localizedDescription)")
    }
}

3. FileManager 使用注意事项 #

  1. 沙盒环境

    • iOS 应用只能访问自己的沙盒,不能直接访问系统的文件。
    • 除非使用 File Provider 等扩展访问外部文件。
  2. 权限管理

    • 对于隐私敏感文件(如照片、麦克风等数据的存储和访问),需要填写 Info.plist 并请求用户权限。
  3. 异常处理

    • 几乎所有 FileManager 操作都可能导致错误,例如路径不存在、权限不足等。建议通过 do-catch 处理所有异常。
  4. 临时文件管理

    • 存储临时数据时,使用 temporaryDirectory。系统会自动清理,但需要确保在不用时删除临时文件。

4. 应用场景 #

  1. 存储用户文档,例如笔记、文本文件、图片。
  2. 缓存网络下载内容到沙盒的 Caches 中。
  3. 临时生成文件,在特定任务完成后移除它们。
  4. 读取和解析日志文件或配置文件。

通过 FileManager,你可以轻松管理应用程序中的文件和目录操作。

FileManager.SearchPathDomainMask 是一个枚举类型,定义了文件系统的域(Domain)范围,用于在检索目录路径时指定特定的作用域,例如用户目录、系统目录等。这些选项在调用 FileManager 的方法(如 urls(for:in:)NSHomeDirectory())时会用到。

它主要与 FileManager.SearchPathDirectory 一起使用,用于指定调用的目录位置(例如:文档目录、缓存目录),并限定查找的作用域(域对象)。


SearchPathDomainMask 的选项 #

以下是 SearchPathDomainMask 的可用值及其含义:

说明
.userDomainMask用户域,表示当前用户特定的沙盒域,例如应用程序的文档、缓存或日志文件。这是 iOS 应用程序中最常用的域。
.localDomainMask本地域,包含对所有用户可见的资源。它通常表示存放在共享位置的资源目录,例如 /Library/Application Support
.networkDomainMask网络域,指的是基于网络的共享目录,例如网络挂载的卷。这一选项设计用于 macOS 平台,在 iOS 上很少使用。
.systemDomainMask系统域,代表操作系统的系统级目录,例如 /System/Library。普通应用无权限访问此域。
.allDomainsMask所有域,包括上述所有域

SearchPathDomainMask 常和 urls(for:in:)path(for:in:) 方法一起使用。

1. .userDomainMask #

  • 沙盒文件系统

  • 用途: 访问属于当前用户的文件目录(文档、缓存、临时文件等)。

  • 示例:

    if let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
        print("Documents Directory: \(documentsDirectory)")
    }
    
  • urls(for:in:) 返回用户在沙盒中的文件夹,适用于 iOS 应用程序,这也是当前绝大部分情况下使用的域。


2. .localDomainMask #

  • 多用户共享目录
  • 用途: 本地目录,可供所有用户访问的共享文件资源。
  • 示例(macOS 平台):
    if let localLibraryDirectory = FileManager.default.urls(for: .libraryDirectory, in: .localDomainMask).first {
        print("Local Library Directory: \(localLibraryDirectory)")
    }
    
  • 输出路径示例:
    /Library
    

3. .networkDomainMask #

  • 基于网络的共享目录
  • 用途: 检索网络挂载的共享卷(macOS 上用于访问网络文件系统)。
  • 示例(macOS 中):
    if let networkCacheDirectory = FileManager.default.urls(for: .cachesDirectory, in: .networkDomainMask).first {
        print("Network Cache Directory: \(networkCacheDirectory)")
    }
    
  • 输出路径示例:
    /Network/Library/Caches
    

4. .systemDomainMask #

  • 系统资源目录
  • 用途: 表示系统级别不可修改的目录,只读访问(如系统库文件)。在应用程序沙盒中不可用。
  • 示例(macOS 中):
    if let systemLibraryDirectory = FileManager.default.urls(for: .libraryDirectory, in: .systemDomainMask).first {
        print("System Library Directory: \(systemLibraryDirectory)")
    }
    
  • 输出路径示例:
    /System/Library
    

5. .allDomainsMask #

  • 结合所有域

  • 用途: 获取所有域(用户、本地、网络、系统)下的目标目录。对于 iOS 应用而言通常不使用,因为沙盒限制无法访问其他域。

  • 示例:

    let allDomains = FileManager.default.urls(for: .documentDirectory, in: .allDomainsMask)
    print("Directories in All Domains: \(allDomains)")
    

注意事项 #

  1. iOS 的沙盒限制:

    • 在 iOS 上,应用程序只能访问 .userDomainMask 相关的目录(因为沙盒限制),无法访问 .localDomainMask.networkDomainMask.systemDomainMask
    • 常用沙盒目录包括:
      • 文档目录:documentDirectory
      • 缓存目录:cachesDirectory
      • 临时目录:temporaryDirectory
  2. macOS 支持更多域:

    • 在 macOS 上,FileManager.SearchPathDomainMask 的其他域(如 .localDomainMask.networkDomainMask)更加常用,因为 macOS 上的文件系统没有 iOS 那样的沙盒限制。
    • Apple 的目录结构:
      • /Users/username/...(用户域)
      • /Library/...(本地域)
      • /System/...(系统域)
      • /Network/...(网络域)
  3. 指定多个域:

    • 如果你需要操作多个域,可以通过按位或 (|) 的方式组合多个域。
    • 示例:
      let domains: FileManager.SearchPathDomainMask = [.userDomainMask, .localDomainMask]
      

总结 #

  1. .userDomainMask(用户域):沙盒范围,常用于 iOS。
  2. .localDomainMask(本地域):共享资源目录,常用于 macOS。
  3. .networkDomainMask(网络域):访问网络挂载资源,macOS 可用。
  4. .systemDomainMask(系统域):仅限操作系统使用,普通 App 无法访问。
  5. .allDomainsMask:包含了上述所有域。

在实践中:

  • 在开发 iOS 应用程序 时,主要使用 .userDomainMask
  • macOS 开发 或涉及更多文件系统操作时,可以使用 .localDomainMask.systemDomainMask 扩展功能。

实用场景:结合 SearchPathDirectory #

FileManager.SearchPathDomainMask 通常和 FileManager.SearchPathDirectory 结合使用,用于定位具体目录中需要操作的文件。

以下枚举提供了多种特定目录类型:

常用 SearchPathDirectory描述
.documentDirectory用户文档目录,数据存储在应用内 Documents 目录中。
.cachesDirectory缓存目录,可存放临时文件,系统会清理。
.libraryDirectory应用的库目录,用于存放指定的支持文件。
.tmpDirectory临时目录,存储的内容会在系统重启后被清除。

示例代码 #

let fileManager = FileManager.default

// 获取沙盒中文档目录
if let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first {
    print("Documents Directory (User Domain): \(documentsDirectory)")
}

// 获取沙盒中缓存目录
if let cachesDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first {
    print("Caches Directory: \(cachesDirectory)")
}

// 获取库目录
if let libraryDirectory = fileManager.urls(for: .libraryDirectory, in: .userDomainMask).first {
    print("Library Directory: \(libraryDirectory)")
}

结果示例(iOS 上沙盒路径) #

  • 文档目录(documentDirectory + .userDomainMask):

    /var/mobile/Containers/Data/Application/1234-5678-ABCD/Documents
    
  • 缓存目录(cachesDirectory + .userDomainMask):

    /var/mobile/Containers/Data/Application/1234-5678-ABCD/Library/Caches
    
  • 库目录(libraryDirectory + .userDomainMask):

    /var/mobile/Containers/Data/Application/1234-5678-ABCD/Library
    
本文共 4599 字,上次修改于 Jan 1, 2025