是否可以从 DocumentFile 获取常规文件?

Posted

技术标签:

【中文标题】是否可以从 DocumentFile 获取常规文件?【英文标题】:Is it possible to get a regular File from DocumentFile? 【发布时间】:2017-01-27 09:51:59 【问题描述】:

对于android,下面的代码返回一个Uri,可以用来创建一个目录对应的DocumentFile。

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_CODE_CUSTOM_FOLDER);

由于库的许多方法都需要一个参数是 java.io.File,我想知道是否可以从 DocumentFile 中获取 java.io.File。

例如,返回的文档树 Uri treeUri 如下:

treeUri.getPath():/tree/primary:DCIM/deeper/evendeeper
treeUri.toString(): content://com.android.externalstorage.documents/tree/primary%3ADCIM%2Fdeeper%2Fevendeeper

以下是 ADM 中显示的目录:

【问题讨论】:

【参考方案1】:

是的,你可以。对于 API 30+,您需要 full storage access。而对于 API 28-,您只需要 Manifest.permission.READ_EXTERNAL_STORAGE

使用SimpleStorage,您可以将DocumentFile 转换为java.io.File

val file: File? = documentFile.toRawFile(context)?.takeIf  it.canRead() 

【讨论】:

【参考方案2】:

是的,但地址可能是 ASCII 格式,您必须将其转换为 UTF-8 以避免像“%2F”这样的文本字符串。我推荐使用 "val decoded = URLDecoder.decode (input," utf-8 ")"

【讨论】:

【参考方案3】:
I am wondering if one can get a java.io.File from a DocumentFile.

是的,大多数情况下你可以。如果用户从主存储或辅助存储中选择“文件”,则可以,因为内容方案与文件或目录的文件路径之间存在一对一的关系。

但如果你真的需要 java.io.File 你最好使用文件选择器。

[更新]

content://com.android.externalstorage.documents/tree/primar%3ADCIM%2Fdeeper%2Fevendeeper 
content://com.android.externalstorage.documents/tree/primary:DCIM/deeper/evendeeper 

如果是这样,例如对应于

 /storage/emulated/0/DCIM/deeper/evendeeper. 

 content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fcom.aaaa.org%2Ffiles%2Fafile.txt
 content://com.android.externalstorage.documents/tree/primary:Android/com.aaaa.org/files/afile.txt

转化

/storage/emulated/0/Android/com.aaa.org/files/afil‌​e.txt

如果你知道一个你就知道他们都知道:这是一对一的关系。

您唯一需要做的就是将content://com.android.externalstorage.documents/tree/primary‌​: 替换为/storage/emulated/0/

这将问题减少到确定/storage/emulated/0/

为此,您必须让用户为所选内容方案选择文件系统路径的根目录。如果无法选择,通常可以通过设备上的文件资源管理器应用程序找到。最后你可以让输入的路径。

与Android SAF (Storage Access FrameWork): Get particular file Uri from TreeUri 或带有标签storage-acccess-framework 的其他帖子中的完全相反。

【讨论】:

感谢您的帮助。如何将 DocumentFile 的实例转换为 java.io.File? 请将所选文档树的 uri.toSting 与同一目录的文件系统路径一起发布。比较。 好的。但是您没有发布相应的文件系统路径。我也是这么求的。 /storage/emulated/0/DCIM 或 /sdcard/DCIM 之类的东西。 您能告诉我如何从 Uri 中获取文件路径吗? 错误的问题。你应该先回答我的问题。重复:该 DCIM 目录的等效文件系统路径是什么?有几个可能性要找出来。你不能使用它的uri。【参考方案4】:

以下代码返回一个Uri,可以用来创建一个目录对应的DocumentFile

不,它没有。它返回一个Uri,可用于创建与文档树相对应的DocumentFile。它不需要代表文件系统上的目录。文档树的表示位置和方式取决于用户选择的DocumentsProvider。该提供者可以做任何它想代表树的事情(例如,使用数据库,使用对服务器的 REST 调用)。

我想知道是否可以从 DocumentFile 中获取 java.io.File。

没有,因为没有文件。

【讨论】:

非常感谢您的及时回答。看起来我们必须采取其他方式 - 更改方法以使用效率低下的 DocumentFile 而不是 File。

以上是关于是否可以从 DocumentFile 获取常规文件?的主要内容,如果未能解决你的问题,请参考以下文章

SAF DocumentFile - 检查路径是不是存在而不在每个文件夹级别创建每个 DocumentFile

正确删除 DocumentFile(尊重 MediaStore)

存储访问框架获取正确的 Uri 路径删除/编辑/获取文件

存储访问框架 - 设置本地 DocumentFile 的最后修改日期

如何在 Android 11 上获取可读文件

如何从 Javascript FileReader 获取文件名?