You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中如何读取DocumentFile的内容(API 26及以上版本)

Android API 26+ 读取SAF返回DocumentFile内容的官方标准方案

你此前尝试的两种方案都不符合官方规范:

  • new File(myDocumentFile.getUri().getPath()) 仅对file://前缀的Uri有效,SAF返回的是content://类型的Uri,其路径字段并非本地文件系统的真实路径,自然无法直接转为File对象
  • 你找到的旧方案是面向Native C/C++层访问文件的特殊场景实现,Java/Kotlin层读取文件完全不需要使用这类Hack方案

官方推荐实现步骤

谷歌官方明确要求,所有content://类型的Uri都应该通过ContentResolver进行读写操作,你仅需读取内容的需求可以通过以下几行代码实现,全程不需要拿到File对象:

步骤1:前置校验(可选但建议)

读取前先校验DocumentFile的有效性,避免后续异常:

// Java示例
if (documentFile != null && documentFile.exists() && documentFile.isFile() && documentFile.canRead()) {
    // 执行读取逻辑
}
// Kotlin示例
if (documentFile?.exists() == true && documentFile.isFile && documentFile.canRead()) {
    // 执行读取逻辑
}

步骤2:通过ContentResolver打开输入流读取内容

使用ContentResolver.openInputStream()拿到输入流后,按常规IO操作读取即可,建议用try-with-resources自动关闭流避免资源泄漏:

读取为字节数组示例(适合小体积备份文件)

// Java示例
byte[] content = null;
try (InputStream inputStream = getContentResolver().openInputStream(documentFile.getUri())) {
    if (inputStream == null) throw new IOException("无法打开目标文件");
    content = new byte[inputStream.available()];
    inputStream.read(content);
} catch (IOException e) {
    e.printStackTrace();
    // 处理读取异常逻辑
}
// Kotlin示例
var content: ByteArray? = null
try {
    contentResolver.openInputStream(documentFile.uri)?.use { inputStream ->
        content = inputStream.readBytes()
    }
} catch (e: IOException) {
    e.printStackTrace();
    // 处理读取异常逻辑
}

大文件分块读取示例(避免OOM)

如果备份文件体积较大,不要一次性读取到内存,按块读取写入本地沙盒目录即可:

// Java示例
File targetSandboxFile = new File(getFilesDir(), "restore_backup.db");
try (InputStream inputStream = getContentResolver().openInputStream(documentFile.getUri());
     FileOutputStream fos = new FileOutputStream(targetSandboxFile)) {
    if (inputStream == null) throw new IOException("无法打开目标文件");
    byte[] buffer = new byte[8192];
    int len;
    while ((len = inputStream.read(buffer)) != -1) {
        fos.write(buffer, 0, len);
    }
    fos.flush();
} catch (IOException e) {
    e.printStackTrace();
}

注意事项

  • 如果需要在应用重启后仍然能访问该文件,需要在拿到Uri后调用getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION),持久化读取权限,避免系统回收临时授权
  • 整个流程不需要申请任何存储权限,SAF的用户选择授权本身已经赋予了应用对应文件的读写权限

内容的提问来源于stack exchange,提问作者Pythogen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 01:42:03