简体   繁体   English

如何知道是否写入流是否会导致java.io.IOException:写入失败:EBADF(错误的文件号)

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

I know there are a number of posts here on the java.io.IOException: write failed: EBADF (Bad file number) exception, but non of them seems to answer my particular question: 我知道在java.io.IOException: write failed: EBADF (Bad file number)上有很多帖子java.io.IOException: write failed: EBADF (Bad file number)异常,但是似乎没有一个可以回答我的特定问题:

Suppose my activity is called with Intent.ACTION_VIEW and I got a Uri via Uri uri = intent.getData() that starts with content:// from which I read some data (for example a pdf file). 假设我的活动被Intent.ACTION_VIEW调用,并且我通过Uri uri = intent.getData()获得了一个Uri ,它以content://开头,我从中读取了一些数据(例如pdf文件)。 Now I want to find out whether I can also write to that Uri to decide whether a "save" button should be shown to the user, or just a "save as" button. 现在,我想确定是否也可以写信给该Uri以决定是否应向用户显示“保存”按钮,还是仅显示“另存为”按钮。

Suppose further that I can successfully open first a ParcelFileDescriptor and finally a FileOutputStream as in 进一步假设我可以成功地首先打开一个ParcelFileDescriptor ,最后一个FileOutputStream

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

such that fileOutputStream != null . 这样fileOutputStream != null

Depending on the Uri it can now happen that if I try to write to fileOutputStream I get the exception: 根据Uri ,如果我尝试写入fileOutputStream ,现在会发生异常:

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

I would like to know in advance whether this will happen without actually touching/changing the file. 我想提前知道在不实际触摸/更改文件的情况下是否会发生这种情况。 One would think that it should be possible to find out whether I can write to a given Uri or not before trying. 有人认为,应该可以在尝试之前找出我是否可以写给定的Uri

How can I achieve that? 我该如何实现?

Additional observations: 其他观察:

I suppose that the above happens when I don't have permission to write to that particular file/uri, but then why does Android let me open a FileOutputStream in the first place? 我想当我没有权限写入该特定文件/ uri时发生以上情况,但是为什么Android首先让我打开FileOutputStream

For testing I use attachments in emails received with Kaiten mail on an ICS device. 为了进行测试,我在ICS设备上使用Kaiten邮件接收的电子邮件中使用附件。 If I my app opens after I click on "save" in Kaiten mail uri matches content://media/external/file/[0-9]* and everything works, if I however clicked on "open" uri matches content://com.kaitenmail.attachmentprovider/[-0-9a-f]*/[0-9]*/VIEW and I run into the above error. 如果我在Kaiten邮件中单击“保存”后我的应用程序打开,则uri匹配content://media/external/file/[0-9]*并且一切正常,如果我单击了“ open” uri匹配content://com.kaitenmail.attachmentprovider/[-0-9a-f]*/[0-9]*/VIEW ,我遇到上述错误。

There are apparently two methods: 显然有两种方法:

  1. One can call 一个可以打电话

     Context.checkCallingUriPermission(Uri uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION) 

    to check whether the calling process is allowed to write to a given Uri . 检查是否允许调用进程写入给定的Uri

    For the cases I could check, on API level < 19 this seems to result in PackageManager.PERMISSION_DENIED whenever the writing to an output stream pointing to uri fails and in PackageManager.PERMISSION_GRANTED in all other cases. 对于情况下,我可以检查,在API级<19,这似乎导致PackageManager.PERMISSION_DENIED每当写入到输出流指向uri失败,并在PackageManager.PERMISSION_GRANTED在所有其他情况。

    For API level >= 19 it however yields PackageManager.PERMISSION_DENIED even if one has previously taken a persisted write permission with getContentResolver().takePersistableUriPermission(Uri uri, int takeFlags) . 对于> = 19的API级别,即使以前使用getContentResolver().takePersistableUriPermission(Uri uri, int takeFlags)获得了持久的写许可权,它也会产生PackageManager.PERMISSION_DENIED In that case however one can use 但是在那种情况下,可以使用

     context.getContentResolver().getPersistedUriPermissions() 

    to get a list of all previously taken permissions and then look through them so see if one has permission to write to a given Uri . 获取所有先前获得的权限的列表,然后仔细检查它们,以便查看是否有写给定Uri权限。

  2. If one got he Uri via an Intent intent one can check its flags via intent.getFlags() and see whether Intent.FLAG_GRANT_WRITE_URI_PERMISSION is set. 如果有人通过Intent intent获得Uri ,则可以通过intent.getFlags()检查其标志,并查看是否设置了Intent.FLAG_GRANT_WRITE_URI_PERMISSION This also seems to be a way to "predict the future". 这似乎也是“预测未来”的一种方式。

Obviously, neither of the above methods can be an excuse to not properly handle exceptions that can occur while writing to the stream. 显然,以上两种方法都不能作为未正确处理写入流时可能发生的异常的借口。

The correct way to test whether any resource is available is to try to use it, and handle the exceptions or errors that result when you can't. 测试任何资源是否可用的正确方法是尝试使用它,并处理无法使用时导致的异常或错误。

Anything else amounts to fortune-telling. 其他任何事情都算命。 You might 你可能

  • test the wrong thing 测试错误的东西
  • test the right thing but get an answer that is correct for the time of the test but not for the time of the actual use. 测试正确的东西,但得到的答案在测试时是正确的,但在实际使用时却不正确。 This can work two ways, both bad: the test says you can't, but later you could: or the test says you can, but later you can't. 这有两种工作方式,但都不好:测试说不能,但是后来却可以:或者测试说可以,但是后来就不能。

Don't try to predict the future. 不要试图预测未来。 Coping with the present is difficult enough. 应对目前的困难已经足够了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Android java.io.IOException:写入失败:EBADF(错误的文件号) - Android java.io.IOException: write failed: EBADF (Bad file number) java.io.IOException:读取失败:EBADF(错误的文件描述符) - java.io.IOException: read failed: EBADF (Bad file descriptor) IOException: write failed: EBADF (Bad file number) - IOException: write failed: EBADF (Bad file number) Android Java IOException从文件描述符/输入流中读取失败的EBADF(错误文件编号) - Android Java IOException read failed EBADF (Bad File Number) From File descriptor/Input Stream Java.io.IOException,“坏文件号”USB连接 - Java.io.IOException, “bad file number” USB connection log4j失败-无法刷新Servlet中的编写器(java.io.IOException:错误的文件描述符) - log4j failure - Failed to flush writer in servlet (java.io.IOException: Bad file descriptor) java.io.IOException:无法删除原始文件moveFileToDirectory - java.io.IOException: Failed to delete original file moveFileToDirectory 遇到 java.io.IOException: open failed: ENOENT (No such file or directory) - Experiencing java.io.IOException: open failed: ENOENT (No such file or directory) java.io.IOException:写入服务器时出错 - java.io.IOException: Error writing to server java.io.IOException:意外的流结束 - java.io.IOException: unexpected end of stream
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM