由于 DocumentFile().fromTreeUri(),DocumentFile.exists() 在尚不存在的路径上总是 returns true
DocumentFile.exists() on a path that doesn't yet exist always returns true due to DocumentFile().fromTreeUri()
我正在尝试使用 DocumentFile(由于存储访问框架)在创建文件之前检查文件是否存在。但是 DocumentFile().fromTreeUri()
删除了可能的 Uri 的不存在部分,然后导致 DocumentFile().exists()
始终 return 为真,无论它是否存在。
我创建了一个简单的例子来证明我的观点。首先我们要求用户select一个目录:
@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");
}
}
}
}
然而,当 DocumentFile.fromTreeUri() 在虚构的 Uri 上是 运行 时,虚假的“/fictionalfile”部分丢失,然后导致 DocumentFile.exists() 函数 return true, 如下图LogCat:
I/STORAGE: FICTIONAL URI: content://com.android.externalstorage.documents/tree/17FA-1C18%3AFileSync%2Ftarget/fictionalFile
I/STORAGE: FICTIONAL DOCUMENTFILE URI: content://com.android.externalstorage.documents/tree/17FA-1C18%3AFileSync%2Ftarget/document/17FA-1C18%3AFileSync%2Ftarget
I/STORAGE: Fictional file exists
(在上面的例子中,我使用的是 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");
}
}
}
}
假设 treeUri
是由 ACTION_OPEN_DOCUMENT_TREE
返回的 Uri
,使用 fromTreeUri()
将 treeUri
包装在 DocumentFile
中,然后调用 findFile()
在 DocumentFile
上提供您要查找的显示名称(例如,fictionalFile
)。如果它 returns null
,则没有与该显示名称匹配的文件。
IOW:
if (DocumentFile.fromTreeUri(this, treeUri).findFile(whatevs) == null) {
// TODO: something
}
不过请注意,"display name" 不一定是文件名。
在我的例子中,当我在 CoroutineWorker 中使用 applicationContext 检查 DocumentFile.fromSingleUri(context, media.fileUri)?.exists() == true
时,DocumentProvider 总是返回 true,当文件从外部应用程序中删除时,例如,在文件管理器中。
问题已通过 uri.isFileExist(context)
解决
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()
我正在尝试使用 DocumentFile(由于存储访问框架)在创建文件之前检查文件是否存在。但是 DocumentFile().fromTreeUri()
删除了可能的 Uri 的不存在部分,然后导致 DocumentFile().exists()
始终 return 为真,无论它是否存在。
我创建了一个简单的例子来证明我的观点。首先我们要求用户select一个目录:
@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");
}
}
}
}
然而,当 DocumentFile.fromTreeUri() 在虚构的 Uri 上是 运行 时,虚假的“/fictionalfile”部分丢失,然后导致 DocumentFile.exists() 函数 return true, 如下图LogCat:
I/STORAGE: FICTIONAL URI: content://com.android.externalstorage.documents/tree/17FA-1C18%3AFileSync%2Ftarget/fictionalFile
I/STORAGE: FICTIONAL DOCUMENTFILE URI: content://com.android.externalstorage.documents/tree/17FA-1C18%3AFileSync%2Ftarget/document/17FA-1C18%3AFileSync%2Ftarget
I/STORAGE: Fictional file exists
(在上面的例子中,我使用的是 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");
}
}
}
}
假设 treeUri
是由 ACTION_OPEN_DOCUMENT_TREE
返回的 Uri
,使用 fromTreeUri()
将 treeUri
包装在 DocumentFile
中,然后调用 findFile()
在 DocumentFile
上提供您要查找的显示名称(例如,fictionalFile
)。如果它 returns null
,则没有与该显示名称匹配的文件。
IOW:
if (DocumentFile.fromTreeUri(this, treeUri).findFile(whatevs) == null) {
// TODO: something
}
不过请注意,"display name" 不一定是文件名。
在我的例子中,当我在 CoroutineWorker 中使用 applicationContext 检查 DocumentFile.fromSingleUri(context, media.fileUri)?.exists() == true
时,DocumentProvider 总是返回 true,当文件从外部应用程序中删除时,例如,在文件管理器中。
问题已通过 uri.isFileExist(context)
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()