Android 文件系统小记

608 阅读5分钟

Android 的文件系统结构主要分为内部存储、外部存储和特殊目录。每个部分都有特定的用途和访问权限。以下是详细介绍:

内部存储

内部存储是设备的内置存储,专门用于保存应用的私有数据。每个应用都有自己的内部存储空间,其他应用不能访问。

  • 路径/data/data/<package_name>/
  • 特点
    • 私有性:数据对应用本身可见,其他应用无法访问。
    • 安全性:在设备被擦除或应用被卸载时,这些数据会被删除。
    • 权限:不需要申请额外权限。

常用路径和 API

  1. 文件存储路径

    • 路径/data/data/<package_name>/files/
    • APIContext.getFilesDir()
    • 使用场景:存储应用的配置文件、用户数据等私有文件。
    File filesDir = context.getFilesDir();
    File myFile = new File(filesDir, "myfile.txt");
    
  2. 缓存存储路径

    • 路径/data/data/<package_name>/cache/
    • APIContext.getCacheDir()
    • 使用场景:存储临时数据或缓存文件,系统在需要时可以清除这些文件。
    File cacheDir = context.getCacheDir();
    File tempFile = new File(cacheDir, "tempfile.tmp");
    
  3. 代码缓存路径

    • 路径/data/data/<package_name>/code_cache/
    • APIContext.getCodeCacheDir()
    • 使用场景:存储优化后的代码或编译后的代码缓存。
    File codeCacheDir = context.getCodeCacheDir();
    

内部存储的使用

// 获取内部存储目录
File internalDir = context.getFilesDir(); // /data/data/<package_name>/files

// 写文件
File file = new File(internalDir, "example.txt");
try (FileOutputStream fos = new FileOutputStream(file)) {
    fos.write("Hello, World!".getBytes());
} catch (IOException e) {
    e.printStackTrace();
}

// 读文件
try (FileInputStream fis = new FileInputStream(file)) {
    byte[] data = new byte[(int) file.length()];
    fis.read(data);
    String content = new String(data, "UTF-8");
    System.out.println(content);
} catch (IOException e) {
    e.printStackTrace();
}

外部存储

外部存储是设备的共享存储区域,可以是内置存储(如主存储)或可移动存储(如 SD 卡)。外部存储可以被多个应用访问,但需要申请相应的权限。

  • 公共外部存储:用于存放用户可见的文件,如图片、音频、视频等。
    • 路径/storage/emulated/0/Environment.getExternalStoragePublicDirectory()
    • 特点
      • 数据对用户和其他应用可见。
      • 用户卸载应用时,这些数据不会被删除。
      • 需要申请读写权限。
  • 应用专属外部存储:用于存放应用的私有数据,但位于外部存储中。
    • 路径/storage/emulated/0/Android/data/<package_name>/
    • 特点
      • 数据对应用本身可见,其他应用无法访问。
      • 应用卸载时,这些数据会被删除。
      • 需要申请读写权限。

常用路径和 API

  1. 公共外部存储路径

    • 路径/storage/emulated/0/ 或特定的公共目录,如 Downloads, Pictures, DCIM, Music, Movies
    • APIEnvironment.getExternalStoragePublicDirectory(String type)
    • 使用场景:存储用户可见的文件,如下载的文件、媒体文件等。
    File publicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
    File publicFile = new File(publicDir, "downloadedfile.txt");
    
  2. 应用专属外部存储路径

    • 路径/storage/emulated/0/Android/data/<package_name>/files/
    • APIContext.getExternalFilesDir(String type)
    • 使用场景:存储应用的私有文件,用户可以通过文件管理器访问,应用卸载时这些文件会被删除。
    File appSpecificDir = context.getExternalFilesDir(null);
    File appSpecificFile = new File(appSpecificDir, "appfile.txt");
    
  3. 应用专属外部缓存路径

    • 路径/storage/emulated/0/Android/data/<package_name>/cache/
    • APIContext.getExternalCacheDir()
    • 使用场景:存储临时缓存文件,系统在需要时可以清除这些文件。
    File externalCacheDir = context.getExternalCacheDir();
    File tempExternalFile = new File(externalCacheDir, "tempfile.tmp");
    

外部存储的使用

// 获取公共外部存储目录
File publicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);

// 获取应用专属外部存储目录
File privateDir = context.getExternalFilesDir(null);

// 写文件到公共外部存储
File publicFile = new File(publicDir, "public_example.txt");
try (FileOutputStream fos = new FileOutputStream(publicFile)) {
    fos.write("Hello, Public World!".getBytes());
} catch (IOException e) {
    e.printStackTrace();
}

// 写文件到应用专属外部存储
File privateFile = new File(privateDir, "private_example.txt");
try (FileOutputStream fos = new FileOutputStream(privateFile)) {
    fos.write("Hello, Private World!".getBytes());
} catch (IOException e) {
    e.printStackTrace();
}

// 动态申请权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this,
          new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
          REQUEST_WRITE_STORAGE);
}

特殊目录

Android 提供了一些特殊的目录,用于存储特定类型的数据,如缓存、临时文件等。

  • 缓存目录:用于存储临时缓存数据,系统在需要空间时可以自动清理这些数据。
    • 内部缓存context.getCacheDir(),路径为 /data/data/<package_name>/cache/
    • 外部缓存context.getExternalCacheDir(),路径为 /storage/emulated/0/Android/data/<package_name>/cache/
  • 代码缓存目录:用于存储应用的优化代码或其他编译后的代码。
    • 路径context.getCodeCacheDir()
  • 临时文件目录:用于存储临时文件,开发者需要自行管理这些文件。
    • 路径context.getExternalFilesDir(Environment.DIRECTORY_TEMPORARY)(API 级别 30+)

缓存文件被称为特殊目录是因为: context.getCacheDir() 被称为特殊目录主要是因为它用于存储应用的临时缓存数据,并且具有一些独特的特性和用途。以下是详细的解释:

特殊性和用途

  1. 临时性

    • 自动管理:缓存目录中的文件是临时文件,系统在需要空间时会自动清理这些文件。
    • 清除策略:当设备存储空间不足时,系统可能会删除缓存目录中的文件以释放空间。开发者无需手动管理这些文件的生命周期。
  2. 私有性

    • 应用专有:缓存目录是应用私有的,其他应用无法访问这些文件。这与其他内部存储路径(如 context.getFilesDir())一样,提供了安全性和数据隔离。
  3. 不需要权限

    • 默认可用:与内部存储中的其他路径类似,访问缓存目录不需要申请任何额外权限。这使得缓存操作简单且高效。
  4. 使用场景

    • 临时存储:适用于存储临时数据,如图片缓存、网络请求缓存等。缓存文件不需要持久保存,可以随时重新生成。
    • 快速访问:由于缓存目录通常存储在设备的内部存储中,因此访问速度较快,适合需要高效读写操作的临时数据。

特殊目录总结

  • 自动管理:系统自动清理,开发者无需手动管理。
  • 私有安全:仅对应用本身可见,确保数据安全。
  • 无需权限:简化了开发流程。
  • 适用场景:临时文件存储、缓存数据等。

访问权限

  • 内部存储:不需要额外权限。
  • 外部存储
    • 读写公共外部存储:需要申请 READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE 权限。
    • 应用专属外部存储:从 Android 10 开始,应用可以不需要申请权限直接访问自己的专属外部存储。

总结

  • 内部存储:私有、安全、无需权限。
  • 外部存储:分为公共和专属,公共需要权限,专属不需要权限(Android 10+)。
  • 特殊目录:用于缓存和临时数据,系统自动管理部分目录。