文件存储:内部存储与外部存储

简介: Android文件存储分内部与外部两类:内部存储(`filesDir`)私有安全、无需权限,适合小量敏感数据;外部存储含应用专属目录(`getExternalFilesDir`)和共享媒体(MediaStore),前者同样私有免权限,后者需适配分区存储。合理选用可避免权限错误、数据丢失或泄露。

文件存储:内部存储与外部存储

背景

前面聊过的 SharedPreferences 和 Room 擅长管理键值对与结构化数据。但实际开发中还有一类需求它们搞不定:存储图片、日志文件、下载的文档、缓存的 JSON 数据等——这些场景就需要用到 Android 的文件存储。

Android 文件存储分为两大块:内部存储(Internal Storage)外部存储(External Storage)。别被名字误导——它们的区别不只是物理位置,权限要求、生命周期、安全隔离才是关键。选错存储位置,轻则功能不生效,重则数据泄露或丢失。

核心概念

内部存储

内部存储是每个应用私有的沙盒目录,位于 /data/data/<包名>/files/。特点:

  • 默认私有:其他应用无法直接访问,用户也看不到。
  • 随应用卸载删除:卸载后数据一并清空。
  • 无需运行时权限:从 API 1 就在用,任何版本都没加过权限限制。
  • 空间有限:和系统分区共享,不适合存大文件。

典型用途:敏感配置、数据库备份、私密密钥等。获取目录的常用 API:

context.filesDir          // /data/data/<包名>/files
context.cacheDir          // /data/data/<包名>/cache(系统可能自动清理)
context.getDir("custom", MODE_PRIVATE)  // /data/data/<包名>/app_custom

外部存储

Android 10(API 29)引入分区存储(Scoped Storage)后,外部存储分两层理解:

  • 应用专属外部目录getExternalFilesDir() 返回 /sdcard/Android/data/<包名>/files/,同样是私有、无需权限、随卸载删除。
  • 共享存储:通过 MediaStore API 访问公共目录(Pictures、Downloads、Music),需要声明权限。

重点记忆:filesDir(内部)和 getExternalFilesDir()(应用专属外部)都不需要运行时权限,都是应用私有。区别在于后者可能位于可插拔存储设备,空间通常更大。

代码实战(Kotlin)

封装一个文件管理工具类,覆盖写入、读取、删除、缓存清理:

import android.content.Context
import java.io.File

object FileHelper {

    // 写入文本到内部存储
    fun writeToInternal(context: Context, filename: String, content: String) {
        val file = File(context.filesDir, filename)
        file.writeText(content) // Kotlin 扩展,默认 UTF-8
    }

    // 从内部存储读取文本
    fun readFromInternal(context: Context, filename: String): String? {
        val file = File(context.filesDir, filename)
        return if (file.exists()) file.readText() else null
    }

    // 写入到应用专属外部存储
    fun writeToExternalAppDir(context: Context, filename: String, content: String) {
        val dir = context.getExternalFilesDir(null)
        dir?.let {
            if (!it.exists()) it.mkdirs()
            File(it, filename).writeText(content)
        }
    }

    // 按类型获取外部缓存子目录(如图片)
    fun getImageCacheDir(context: Context): File? {
        return context.externalCacheDir?.let {
            val imgDir = File(it, "images")
            if (!imgDir.exists()) imgDir.mkdirs()
            imgDir
        }
    }

    // 删除单个文件
    fun deleteFile(context: Context, filename: String): Boolean {
        return File(context.filesDir, filename).delete()
    }

    // 计算并清理缓存
    fun clearCache(context: Context): Long {
        var totalSize = 0L
        context.cacheDir.walkTopDown().forEach { file ->
            if (file.isFile) {
                totalSize += file.length()
                file.delete()
            }
        }
        return totalSize // 返回清理掉的总字节数
    }
}

Activity 调用示例:

class FileDemoActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_file_demo)

        // 写入配置到内部存储
        FileHelper.writeToInternal(this, "user_config.txt", "darkMode=true")
        // 写入日志到外部专属目录
        FileHelper.writeToExternalAppDir(this, "log.txt",
            "app started at ${System.currentTimeMillis()}")

        // 读取
        val config = FileHelper.readFromInternal(this, "user_config.txt")
        Log.d("FileDemo", "读取配置: $config")

        // 清理缓存
        val freed = FileHelper.clearCache(this)
        Log.d("FileDemo", "清理缓存: $freed bytes")
    }
}

避坑指南

坑一:混淆"外部存储"和"SD 卡"。 getExternalFilesDir() 通常指向机身存储的模拟 SD 卡分区,不一定是物理 SD 卡。不要把路径写死为 /sdcard/

坑二:直接用文件路径字符串拼接。 永远用 context.filesDircontext.cacheDirgetExternalFilesDir() 等 API 获取路径,兼容不同厂商和 Android 版本。

坑三:不检查外部存储可用性。 外部存储可能被卸载或只读:

val isAvailable = Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED

坑四:大文件放内部存储。 图片、视频、日志等大文件应放到外部存储,内部存储空间有限且会影响系统性能。

坑五:忽略 Android 10+ 分区存储。 targetSdkVersion >= 29 时,访问共享目录必须用 MediaStore 或 SAF(Storage Access Framework),传统文件路径操作会失效。

坑六:忘记清理缓存。 cacheDirexternalCacheDir 系统可能自动清理,但不要依赖这一点——在合适时机主动调用 clearCache() 是良好习惯。

总结

Android 文件存储的选择逻辑很简单:私密小文件放内部(filesDir),大文件放应用专属外部目录(getExternalFilesDir),共享媒体用 MediaStore。 内部存储和专属外部目录都无需权限、都是私有;缓存目录(cacheDir / externalCacheDir)适合临时文件,系统可能自动回收。

把文件存储和前面学过的 SharedPreferences、Room 放在一起看,Android 数据持久化体系就完整了:键值对用 SharedPreferences / DataStore,结构化数据用 Room,二进制和大文件用文件存储。 根据数据特征选对存储方式,比炫技代码重要得多。

相关文章
|
4天前
|
云安全 人工智能 运维
阿里云SecOps Agent,全新安全跨产品执行体验
自然语言驱动 云安全中心/WAF/CFW/ 等多款安全产品联动
1595 2
|
1天前
|
人工智能 定位技术 SEO
我学 GEO 第 15 天:终于知道AI GEO该如何做?
我是暴走的莉莉酱,边旅行边研究AI GEO的数字游民。专注普通人如何提升“AI可见度”——让AI在回答用户问题时准确识别、理解并推荐你。不讲玄学,只做可测、可调、可持续的GEO实践。
348 122
|
4天前
|
机器学习/深度学习 人工智能 调度
🐴 HappyHorse 1.1 现已上线阿里云百炼!快来查收模型使用指南,现在调用享 6 折~
HappyHorse 1.1 是新一代视频生成大模型,全面升级动态表现力、角色一致性、指令遵循、视觉质感与音画协同能力。支持I2V/T2V/R2V三类生成,适配短剧、电商广告、品牌营销等场景,提供高质、流畅、可控的AI视频生产力。
577 3
🐴 HappyHorse 1.1 现已上线阿里云百炼!快来查收模型使用指南,现在调用享 6 折~
|
14天前
|
缓存 测试技术 API
Qwen 3.7 Plus 与 Max 实测:性价比与多模态能力差异解析(2026)
2026 年 6 月 1 日,阿里悄无声息地发布了 Qwen 3.7 Plus,距 Qwen 3.7 Max 上线刚好 11 天。同样的 1M 上下文,同样的 35 小时自治上限。但价格才是头条:Plus 是 0.40/M输入,Max是 2.50/M——便宜约 6 倍——并且还能看图、看视频。Vision Arena 上 Plus 已经排到 #16。所以这周真正值得讨论的问题不是”要不要为视觉能力买单”,而是”Max 凭什么用 6 倍价格换来 2 个百分点的 benchmark 领先”。
|
15天前
|
JavaScript 定位技术 API
CodeGraph 爆火:编程 Agent 需要的不是更多上下文,而是一张提前画好的代码地图
CodeGraph 是一款爆火的本地代码智能工具,通过 tree-sitter 解析 AST 构建结构化知识图谱(存于 SQLite),为编程 Agent 提前生成“代码地图”。它显著降低 Agent 在中大型项目中的探索成本——实测工具调用减少71%、Token 降57%、速度提升46%,支持19+语言及主流框架路由识别,完全离线、无需 API Key。
910 11
CodeGraph 爆火:编程 Agent 需要的不是更多上下文,而是一张提前画好的代码地图
|
8天前
|
缓存 人工智能 运维
GLM 5.2自托管全流程实战:硬件选型、vLLM/SGLang部署与成本盈亏测算
2026年智谱发布GLM 5.2超大混合专家模型,区别于以往仅开放API的闭源大模型,该模型权重以MIT开源协议对外发布,企业与开发者可完整下载、本地审计、私有化部署,实现数据不出环境、自定义微调、自主调度推理资源。GLM 5.2拥有753B总参数,原生支持百万级上下文窗口,在代码生成、长文档推理、数学逻辑等多项基准测试中对标国际顶尖商用模型,是首款可完整自托管的前沿代码向大模型。
651 0
|
2天前
|
消息中间件 人工智能 Kafka
AI 时代,实时入湖正在告别 ETL:从 Kafka 到 Iceberg 的架构减法
本文围绕“零 ETL”这一趋势,讨论流数据入湖为什么需要做架构减法,并结合 Kafka × Table Bucket 的实践,分析一种将通用入湖能力前移到消息与表存储链路中的方案,如何在降低复杂度的同时,兼顾实时性、一致性、Schema 演进、CDC 语义与开放生态兼容。
192 121
|
2天前
|
人工智能 监控 前端开发
Electron 监控:让桌面 Agent 监控触手可及
一行代码实现Electron桌面端全景监控,自动还原崩溃现场、预警内存泄漏、全链路追踪、 SSE流式响应与交互埋点,让 AI 助手运行状态清晰可见,助力快速恢复稳定与流畅。
182 125
|
11天前
|
人工智能 自然语言处理 算法
阿里云百炼Qwen 3.7 Plus与Max实测全解:性价比与多模态能力、成本深度对比
2026年,阿里云百炼平台推出的Qwen 3.7系列成为企业与开发者落地AI应用的核心选择,其中Qwen 3.7 Max与Plus作为两大旗舰版本,定位差异显著:Max是纯文本推理旗舰,专注高强度智能体与复杂逻辑任务;Plus则是多模态全能版,在保留强大文本能力的同时,补齐图像、视频理解能力,且价格大幅降低。本文基于2026年最新实测数据,从核心参数、文本能力、多模态能力、智能体表现、性价比与场景选型六大维度,全面解析两款模型的差异,为用户提供精准选型参考。
537 0