我正在尝试使用DocumentFile(由于Storage Access Framework)在创建文件之前检查文件是否存在。但是DocumentFile().fromTreeUri()删除了可能的Uri中不存在的部分,这将导致DocumentFile().exists()始终返回true,无论它是否存在。

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

@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添加到路径中(从而使它成为不存在的文件),然后检查它是否存在:

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");
            }
        }
    }
}


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


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


(在上面的示例中,我使用的是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。有什么想法吗?

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");
            }
        }
    }
}

最佳答案

给定treeUriUri返回的ACTION_OPEN_DOCUMENT_TREE,请使用treeUriDocumentFile包裹在fromTreeUri()中,然后在该findFile()上调用DocumentFile提供所需的显示名称(例如fictionalFile)。如果返回null,则没有与显示名称匹配的文件。

IOW:

if (DocumentFile.fromTreeUri(this, treeUri).findFile(whatevs) == null) {
  // TODO: something
}


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

08-04 07:52