首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在尚未存在的路径上的DocumentFile.exists()总是返回true,因为DocumentFile().fromTreeUri()

在尚未存在的路径上的DocumentFile.exists()总是返回true,因为DocumentFile().fromTreeUri()
EN

Stack Overflow用户
提问于 2018-08-02 20:06:13
回答 2查看 2.6K关注 0票数 6

我正在尝试使用DocumentFile (由于存储访问框架)在创建文件之前检查它是否存在。但是DocumentFile().fromTreeUri()删除了可能的Uri中不存在的部分,这会导致DocumentFile().exists()始终返回true,而不管它是否存在。

我创建了一个简单的例子来说明我的观点。首先,我们要求用户选择一个目录:

代码语言:javascript
复制
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    // Ask the user for the source folder
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
    startActivityForResult(intent, 100);
}

在响应时,我们将/fictionalFile添加到路径(从而使其成为一个不存在的文件),然后检查它是否存在:

代码语言:javascript
复制
public void onActivityResult(int requestCode, int resultCode, Intent resultData)
{
    if (resultCode == RESULT_OK)
    {
        if(requestCode == 100)
        {
            Uri fictionalURI = Uri.parse(resultData.getData()+"/fictionalFile");
            DocumentFile fictionalFile = DocumentFile.fromTreeUri(this, fictionalURI);
            Log.i("STORAGE", "FICTIONAL URI: "+fictionalURI);
            Log.i("STORAGE", "FICTIONAL DOCUMENTFILE URI: "+fictionalFile.getUri());

            if(fictionalFile.exists())
            {
                Log.i("STORAGE", "Fictional file exists");
            }
        }
    }
}

但是,当DocumentFile.fromTreeUri()在虚构的Uri上运行时,假的"/fictionalfile“部分会丢失,这会导致DocumentFile.exists()函数返回true,如下所示:

I/存储:虚构URI: content://com.android.externalstorage.documents/tree/17FA-1C18%3AFileSync%2Ftarget/fictionalFile I/存储:虚构的DOCUMENTFILE URI: content://com.android.externalstorage.documents/tree/17FA-1C18%3AFileSync%2Ftarget/document/17FA-1C18%3AFileSync%2Ftarget I/存储:存在虚构的文件

(在上面的示例中,我使用SD卡,因此使用长路径名称)

是否有另一种方法来检查尚未创建的DocumentFile是否存在?用例是,当将文件从目录A复制到目录B时,在开始传输之前,我要检查目录B中是否已经存在上述文件。

更新:--我现在意识到使用DocumentFile.fromTreeUri()是错误的,我应该使用DocumentFile.fromSingleUri()。这很有帮助,但是在新文件上运行.exists()时,我得到了W/DocumentFile: Failed query: java.lang.UnsupportedOperationException: Unsupported Uri content://com.android.externalstorage.documents/tree/17FA-1C18%3AFileSync%2Ftarget/fictionalFile。有什么想法吗?

代码语言:javascript
复制
public void onActivityResult(int requestCode, int resultCode, Intent resultData)
{
    if (resultCode == RESULT_OK)
    {
        if(requestCode == 100)
        {
            Uri fictionalURI = Uri.parse(resultData.getData()+"/fictionalFile");
            DocumentFile fictionalFile = DocumentFile.fromSingleUri(this, fictionalURI);
            Log.i("STORAGE", "FICTIONAL URI: "+fictionalURI);
            Log.i("STORAGE", "FICTIONAL DOCUMENTFILE URI: "+fictionalFile.getUri());

            if(fictionalFile != null && fictionalFile.exists())
            {
                Log.i("STORAGE", "Fictional file exists");
            }
        }
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-08-02 21:55:34

假定treeUriACTION_OPEN_DOCUMENT_TREE返回的Uri,使用fromTreeUri()treeUri包装在DocumentFile中,然后在DocumentFile上调用findFile(),提供您要查找的显示名称(例如fictionalFile)。如果它返回null,则没有匹配该显示名称的文件。

IOW:

代码语言:javascript
复制
if (DocumentFile.fromTreeUri(this, treeUri).findFile(whatevs) == null) {
  // TODO: something
}

但请注意,“显示名称”不一定是文件名。

票数 6
EN

Stack Overflow用户

发布于 2020-08-20 14:50:00

在我的例子中,当我用DocumentFile.fromSingleUri(context, media.fileUri)?.exists() == true在CoroutineWorker中签入applicationContext时,当文件从外部应用程序中删除时(例如在文件管理器中),DocumentProvider总是返回true。

这个问题用uri.isFileExist(context)解决了。

代码语言:javascript
复制
import android.content.Context
import android.net.Uri
import androidx.documentfile.provider.DocumentFile

fun DocumentFile?.isFile() = this?.isFile ?: false

fun DocumentFile?.isExists() = this?.exists() ?: false

fun DocumentFile?.getLength() = this?.length() ?: 0

fun DocumentFile?.isFileExist() = isFile() && isExists() && getLength() > 0

fun Uri.isFileExist(context: Context) =
    DocumentFile.fromSingleUri(context, this).isFileExist()

更新:下面的解决方案在android 10+上正确工作。最后,我更换了它,使它在所有版本的android上都能正常工作。

代码语言:javascript
复制
fun Uri.isFileExist(context: Context): Boolean {
    var isExist = false
    runCatching {
        context.contentResolver.openInputStream(this)?.let {
             it.close()
             isExist = true
        }
    }
    return isExist
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51661385

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档