如何知道写入流是否会导致 java.io.IOException: write failed: EBADF (Bad file number)

How to know whether writing to stream would result in java.io.IOException: write failed: EBADF (Bad file number)

我知道这里有很多关于 java.io.IOException: write failed: EBADF (Bad file number) 例外的帖子,但似乎没有一个能回答我的特定问题:

假设我的 activity 是用 Intent.ACTION_VIEW 调用的,我通过 Uri uri = intent.getData() 得到了一个 Uri,它以 content:// 开头,我从中读取了一些数据(例如 pdf 文件)。现在我想知道我是否也可以写入 Uri 来决定是向用户显示 "save" 按钮,还是只显示 "save as" 按钮。

进一步假设我可以首先成功打开 ParcelFileDescriptor,最后打开 FileOutputStream,如

ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "w");
FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());

这样 fileOutputStream != null.

根据 Uri 现在可能会发生,如果我尝试写入 fileOutputStream 我得到异常:

Exception=java.io.IOException: write failed: EBADF (Bad file number)

我想提前知道这是否会在没有 touching/changing 文件的情况下发生。人们会认为应该有可能在尝试之前找出我是否可以写入给定的 Uri

我怎样才能做到这一点?

补充观察:

我想当我没有权限写入那个特定的 file/uri 时会发生上述情况,但是为什么 Android 让我在第一个打开 FileOutputStream地点?

为了测试,我使用了在 ICS 设备上通过 Kaiten 邮件收到的电子邮件中的附件。如果我在 Kaiten 邮件中单击 "save" 后我的应用程序打开 uri 匹配 content://media/external/file/[0-9]* 并且一切正常,但是如果我单击 "open" uri 匹配 content://com.kaitenmail.attachmentprovider/[-0-9a-f]*/[0-9]*/VIEW 和我 运行 进入上面的错误。

显然有两种方法:

  1. 可以打电话

    Context.checkCallingUriPermission(Uri uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
    

    检查是否允许调用进程写入给定的 Uri

    对于我可以检查的情况,在 API 级别 < 19 这似乎导致 PackageManager.PERMISSION_DENIED 每当写入指向 uri 的输出流失败并且在 PackageManager.PERMISSION_GRANTED 在所有其他情况下。

    对于 API 级别 >= 19,它会产生 PackageManager.PERMISSION_DENIED,即使之前已经使用 getContentResolver().takePersistableUriPermission(Uri uri, int takeFlags) 获得了持久写入权限。然而,在那种情况下,可以使用

    context.getContentResolver().getPersistedUriPermissions()
    

    获取所有先前获得的权限的列表,然后查看它们,看看是否有权限写入给定的 Uri

  2. 如果通过 Intent intent 获得了 Uri,可以通过 intent.getFlags() 检查其标志并查看是否设置了 Intent.FLAG_GRANT_WRITE_URI_PERMISSION。这似乎也是 "predict the future".

  3. 的一种方式

显然,上述两种方法都不能成为不正确处理写入流时可能发生的异常的借口。

测试任何资源是否可用的正确方法是尝试使用它,并处理当您不能使用时导致的异常或错误。

其他什么都算算命。你可能

  • 测试错了东西
  • 测试正确的东西,但得到的答案在测试时是正确的,但在实际使用时却不正确。这有两种方法,两种方法都不好:测试说你不能,但后来你可以:或者测试说你可以,但后来你不能。

不要试图预测未来。应付现在已经够难的了。