应用程序的文档目录是用户文件的永久存储位置,这些文件应在会话之间保留并从备份中恢复。根据 Apple File System Programming Guide, 2026,在 iOS 上,Documents 目录会自动包含在 iCloud 备份中,这与缓存和临时目录不同。正确使用文档目录可确保用户文件在应用程序更新或重新安装时不会丢失。
要点
context.filesDir,需手动管理备份文档目录 — 应用程序沙盒中的专用存储空间,用于永久存储用户文件。与缓存不同,此目录中的文件被视为对用户重要:系统在空间不足时不会删除它们,在应用程序更新时保留,并在设备同步时备份。在 iOS 上,Documents 目录是 Sandbox 容器的一部分,并自动包含在 iCloud 备份中。在 Android 上没有直接等效项 — context.filesDir 作为等效项,也用于永久文件,但没有内置的备份机制。
文档目录与 Android 上的内部存储(Internal Storage)之间的差异很小:两者都位于应用程序沙盒中,两者都在卸载时被删除,两者都对其他应用程序不可访问。主要区别是语义上的:Documents Directory 假定文件是由用户创建或导入的,而 Internal Storage 可能包含应用程序的内部文件(数据库、配置)。在 iOS 上,差异更为显著:Documents 会自动备份,而 Library/Application Support 则不会。这会影响存储策略:在 Documents 中仅放置用户希望在新设备上恢复的内容,在 Application Support 中放置应用程序可以重新创建的内部数据。
沙盒架构确保其他应用程序无法访问您的应用程序的文档目录。在 iOS 上,未经越狱无法访问其他应用程序的 Documents。在 Android 上,root 访问权限允许读取任何应用程序的 filesDir,因此机密数据(令牌、加密密钥)必须使用 AndroidX Security 库中的 EncryptedSharedPreferences 或 EncryptedFile 进行额外保护。
文档目录中应放置对用户有价值且在应用程序重启或设备恢复后必须可用的数据。并非所有文件都适合存储在此目录中 — 选择取决于数据类型和使用场景。
用户文件 — 文档目录的主要内容。这些可以是编辑器中创建的文本文档、应用程序相机拍摄的图像、导出的 PDF 报告、录音、笔记。每个此类文件都由用户或应其要求创建,并且必须随时可用。在 iOS 上,Documents 中的文件显示在系统 Files 应用程序中,允许用户通过标准文件管理器进行管理。在 Android 上没有类似的显示 — 应用程序必须自行提供查看已保存文件的界面。
SQLite 数据库和设置文件通常存储在文档目录旁边,但不在其内部。在 iOS 上,数据库放置在 Library/Application Support 中,因为它们不应显示在 Files 应用程序中并单独备份。在 Android 上,数据库默认通过 Room 或 SQLiteOpenHelper 在 /data/data/<package>/databases/ 中创建。如果数据库包含用户内容(笔记、日记、财务记录),可以将其放置在 filesDir 中以便通过系统进行备份。Room 允许通过 RoomDatabase.Builder 回调指定用于存储数据库的自定义目录。
val dbFile = File(context.filesDir, "user_database.db")
val db = Room.databaseBuilder<AppDatabase>(
context,
dbFile.absolutePath
).build()
用户从其他应用程序导入或从您的应用程序导出的文件也应存储在文档目录中。在 iOS 上,通过 UIDocumentPickerViewController 导入时,如果使用 asCopy: true 参数,会自动将文件副本放入 Documents。在 Android 上,通过 SAF 对话框导入也会在应用程序沙盒中创建文件副本。导出数据时(例如,创建包含联系人的 CSV 文件),首先将文件保存在 Documents/filesDir 中,然后通过 Share Sheet 提供给用户分享。这确保即使用户在发送后忘记保存文件,副本仍保留在应用程序中供以后使用。
在 Android 上,文档目录的功能由 context.filesDir 执行。此外,SD 卡上还有 context.externalFilesDir 目录,但它不保证数据保存。让我们看看使用这些目录的主要方法。
filesDir — Android 上应用程序永久文件的主目录。它位于应用程序沙盒中,卸载时完全删除。要获取 File 实例,请使用 context.filesDir,它返回 /data/data/<package>/files/ 目录的路径。要创建和读取文件,请使用 Java/Kotlin 中的标准 File 操作或 Context 方法 openFileInput() 和 openFileOutput(),它们接受文件名并返回 FileInputStream/FileOutputStream。openFileOutput() 方法在文件尚不存在时自动在 filesDir 中创建它,并允许指定访问模式:MODE_PRIVATE(仅当前应用程序)、MODE_APPEND(追加)或 MODE_WORLD_READABLE(已弃用,API 24+ 后不使用)。
val fileName = "report.pdf"
val content = "PDF content".toByteArray()
context.openFileOutput(fileName, Context.MODE_PRIVATE).use { stream ->
stream.write(content)
}
val bytes = context.openFileInput(fileName).use { stream ->
stream.readBytes()
}
在 Android 10+ 上,Scoped Storage 模型不影响 filesDir — 对应用程序自身沙盒的访问保持完整。filesDir 内的所有读写操作不需要额外权限。但是,尝试通过 filesDir 访问其他应用程序的文件时,您将收到异常。对于文件交换,请使用 FileProvider,它会创建临时 content URI 以将文件传输到其他应用程序。FileProvider 通过 <provider> 标签在 AndroidManifest.xml 中声明,并在路径 XML 文件中配置。这是在应用程序之间传输文件的标准机制,例如在通过带有 ACTION_SEND 的 Intent 发送图像时使用。
在 iOS 上,Documents Directory 是应用程序 Sandbox 容器的一部分,具有特殊状态。此目录中的文件自动包含在 iCloud 备份中,显示在 Files 应用程序中,并在通过 App Store 更新应用程序时保留。
自动备份 Documents — iOS 的关键优势。当用户将设备连接到 iTunes 或启用 iCloud Backup 时,Documents/ 中的所有文件都会复制到备份中。在新设备上恢复时,用户无需额外操作即可获得所有文件。但是,如果应用程序在 Documents 中存储大量数据,这一优势就变成了劣势:备份时间增加,iCloud 存储空间可能很快耗尽。因此,在 Documents 中只应存储用户在恢复时真正需要的文件。临时文件、缓存和可重建的数据应放在 Caches 或 Library/Application Support 中。Apple 建议通过 isExcludedFromBackup 属性将可从互联网重新下载的文件排除在备份之外。
let fm = FileManager.default
let docsURL = fm.urls(
for: .documentDirectory,
in: .userDomainMask
).first!
let fileURL = docsURL.appendingPathComponent("notes.txt")
let text = "笔记内容"
try text.write(to: fileURL, atomically: true, encoding: .utf8)
iCloud Drive 允许在同一用户的不同设备之间同步 Documents 中的文件。要启用同步,应用程序应使用 NSDocument 或 UIDocument API,这些 API 自动管理版本控制和冲突解决。替代方法 — 使用带有 CloudKit 的 iCloud,它提供更灵活的同步控制,但需要在 CloudKit Dashboard 上进行配置。使用 iCloud Drive 时,请确保正确处理编辑冲突(合并或后写胜出),并通过应用程序界面通知用户同步状态。iCloud 不保证即时同步 — 延迟可能从几秒到几分钟不等,具体取决于文件大小和连接质量。对于关键数据,请使用事务性写入和版本控制,以便在冲突时可以恢复文件的先前版本。
正确选择 Documents Directory 和 Cache Directory 决定了用户数据存储的可靠性。选择错误要么导致数据丢失(如果重要文件存储在缓存中),要么导致备份溢出(如果临时文件存储在 Documents 中)。
| 标准 | Documents Directory | Cache Directory |
|---|---|---|
| 保存保证 | 高 — 不会被系统删除 | 低 — 可能被清除 |
| 备份(iOS) | 自动在 iCloud 中 | 不备份 |
| 用户可见性(iOS) | 在 Files 应用程序中 | 隐藏 |
| 更新时清除 | 不清除 | 可能被清除 |
| 推荐大小 | 任意,但通过设置控制 | 最多 100–200 MB |
| 数据类型 | 用户文件 | 临时可重建数据 |
最佳实践使用文档目录包括几个关键规则。首先,在从此目录删除文件之前始终请求用户确认。与缓存不同,删除文档可能导致用户内容的不可逆丢失。其次,实施文件版本控制:在覆盖现有文件时,使用 _backup 后缀保留先前版本或使用快照机制。第三,为用户提供从文档目录查看、重命名、删除和导出文件的界面。在 iOS 上,Documents 中的文件自动显示在 Files 中,在 Android 上需要实现自己的文件管理器或使用第三方库。
特别关注应用程序更新时的数据迁移。如果新版本更改了文件存储结构(例如,将数据从一个子目录移动到另一个子目录或更改文件格式),则在更新后的首次启动时实施一次性迁移。将数据架构版本号存储在 SharedPreferences 中,并在不匹配时启动迁移。在迁移完成之前不要删除旧文件 — 在发生故障时用户不应丢失数据。如果迁移包括格式转换(例如,从 JSON 迁移到 SQLite),将原始文件作为备份保存在单独的目录中,并包含迁移日期。用户应能够在更新后的前 30 天内通过应用程序设置撤销更改,如 Apple Human Interface Guidelines 所建议。
常见问题
Documents 显示在 Files 应用程序中并自动在 iCloud 中备份。Application Support 不显示在 Files 中,默认不备份。选择 Application Support 用于不需要向用户显示的应用程序内部数据。
是的,在删除帐户时,请用户清理与此帐户关联的所有本地文件。显示带有„删除所有本地数据?”问题的对话框,并列出哪些文件将受到影响。这是 GDPR 要求和 App Store 及 Google Play 政策的合规要求。
在 iOS 上,只需从 iCloud 或 iTunes 备份恢复设备 — Documents 中的文件会自动恢复。在 Android 上,使用 Google Drive Backup API 备份 filesDir 中的文件,或通过云服务实施导出。
在 iOS 上,用户可以通过 Files 应用程序删除文件。在 Android 上,只有通过您的应用程序界面才能删除。建议为文档实施回收站功能,可在删除后 30 天内恢复,以防止意外数据丢失。
不需要额外操作 — iOS 和 Android 在通过 App Store 或 Google Play 更新时会自动保留文档目录。但是,如果存储结构发生变化,在首次启动新版本时实施数据迁移,检查设置中的架构版本号。
总结
context.filesDir 作为等效 — 文件在更新时保留,但没有内置的备份机制我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。