【问题标题】: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)
【发布时间】:2015-11-12 09:55:07
【问题描述】:

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

假设我的活动是用Intent.ACTION_VIEW 调用的,我通过Uri uri = intent.getData() 得到了一个Uri,它以content:// 开头,我从中读取了一些数据(例如pdf 文件)。现在我想知道我是否也可以写信给Uri 来决定是应该向用户显示“保存”按钮,还是只显示“另存为”按钮。

进一步假设我可以先成功打开一个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)

我想提前知道这是否会在不实际接触/更改文件的情况下发生。有人会认为,在尝试之前应该可以确定我是否可以写信给给定的Uri

我怎样才能做到这一点?

补充意见:

我想当我无权写入该特定文件/uri时会发生上述情况,但是为什么Android首先让我打开FileOutputStream

为了测试,我在 ICS 设备上使用 Kaiten 邮件收到的电子邮件中的附件。如果我在 Kaiten 邮件中单击“保存”uri 匹配 content://media/external/file/[0-9]* 后打开我的应用程序并且一切正常,但是如果我单击“打开”uri 匹配 content://com.kaitenmail.attachmentprovider/[-0-9a-f]*/[0-9]*/VIEW 并且遇到上述错误。

【问题讨论】:

  • public static StructStat android.system.Os#fstat(FileDescriptor fd) 呢?我知道它的 API 21...
  • 看起来这可能是一个一般的解决方案,但我需要这个工作到 API 14...
  • 好的,但是File#canWrite() 呢?您需要将您的 Uri 转换为 File 虽然...
  • 我不明白这个问题。当你得到异常时,你就知道它已经发生了。 为什么会发生是另一个问题。 Android不应该允许它。我怀疑你正在写一个无效的pfd 对象。否则这是一个 Android 错误。
  • @pskink:我认为我无法从以Uri 开头的File 获得content:// 还是我错过了什么? @EJP:我想知道是否可以在不修改文件的情况下写入文件。但是,我只有在尝试写入后才得到异常。

标签: java android io outputstream


【解决方案1】:

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

其他任何事情都相当于算命。你可能

  • 测试错误
  • 测试正确的东西,但得到的答案在测试时是正确的,但在实际使用时不是正确的。这可以通过两种方式起作用,都不好:测试说你不能,但后来你可以;或者测试说你可以,但后来你不能。

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

【讨论】:

  • 我在这里要做的是创建一个直观的用户界面。我认为这是试图预测未来的完全正当理由。当然,仍然需要适当地处理异常。
  • 尝试预测未来不可能有正当理由,原因很简单,就是无法做到。
【解决方案2】:

显然有两种方法:

  1. 可以打电话

    Context.checkCallingUriPermission(Uri uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
    

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

    对于我可以检查的情况,在 API 级别 uri 的输出流失败时,这似乎会导致PackageManager.PERMISSION_DENIED,而在所有其他情况下会导致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。这似乎也是一种“预测未来”的方式。

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

【讨论】:

    猜你喜欢
    • 2019-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-21
    • 1970-01-01
    • 2013-12-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多