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
相关产品推荐
相关产品推荐

