Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/198.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 什么会导致只读文件的EIO关闭(2)失败?_Java_Android_C_Linux_Posix - Fatal编程技术网

Java 什么会导致只读文件的EIO关闭(2)失败?

Java 什么会导致只读文件的EIO关闭(2)失败?,java,android,c,linux,posix,Java,Android,C,Linux,Posix,我正在调查Android上的一个问题,其中由于无法关闭文件而引发了IOException: java.io.IOException: close failed: EIO (I/O error) at libcore.io.IoUtils.close(IoUtils.java:41) at java.io.FileInputStream.close(FileInputStream.java:121) at com.adamrosenfield.wordswithcrosse

我正在调查Android上的一个问题,其中由于无法关闭文件而引发了
IOException

java.io.IOException: close failed: EIO (I/O error)
    at libcore.io.IoUtils.close(IoUtils.java:41)
    at java.io.FileInputStream.close(FileInputStream.java:121)
    at com.adamrosenfield.wordswithcrosses.io.JPZIO.convertJPZPuzzle(JPZIO.java:191)
    at com.adamrosenfield.wordswithcrosses.net.AbstractJPZDownloader.download(AbstractJPZDownloader.java:56)
    at com.adamrosenfield.wordswithcrosses.net.AbstractJPZDownloader.download(AbstractJPZDownloader.java:41)
    at com.adamrosenfield.wordswithcrosses.net.AbstractDownloader.download(AbstractDownloader.java:112)
    at com.adamrosenfield.wordswithcrosses.net.AbstractDownloader.download(AbstractDownloader.java:108)
    at com.adamrosenfield.wordswithcrosses.net.Downloaders.download(Downloaders.java:257)
    at com.adamrosenfield.wordswithcrosses.BrowseActivity.internalDownload(BrowseActivity.java:702)
    at com.adamrosenfield.wordswithcrosses.BrowseActivity.access$6(BrowseActivity.java:696)
    at com.adamrosenfield.wordswithcrosses.BrowseActivity$7.run(BrowseActivity.java:691)
    at java.lang.Thread.run(Thread.java:856)
Caused by: libcore.io.ErrnoException: close failed: EIO (I/O error)
    at libcore.io.Posix.close(Native Method)
    at libcore.io.BlockGuardOs.close(BlockGuardOs.java:75)
    at libcore.io.IoUtils.close(IoUtils.java:38)
    ... 11 more
有关守则:

public static void convertJPZPuzzle(File jpzFile, File destFile,
        PuzzleMetadataSetter metadataSetter) throws IOException {
    FileInputStream fis = new FileInputStream(jpzFile);
    try {
        DataOutputStream dos = new DataOutputStream(new FileOutputStream(destFile));
        try {
            if (!convertJPZPuzzle(fis, dos, metadataSetter)) {
                throw new IOException("Failed to convert JPZ file: " + jpzFile);
            }
        } finally {
            dos.close();
        }
    } finally {
        fis.close();
    }
}
完整的来源是

正在从行
fis.close()
中引发异常。通过阅读Android源代码,我可以看出,
FileInputStream.close()
只是调用了本机代码中的底层文件描述符

手册页面似乎没有指定导致
EIO
错误的原因,它们只是说“发生了I/O错误”。或者“如果在close()期间读取或写入文件系统时发生了I/O错误”。MacOSX手册页称,在这些系统上,“以前未提交的写入(2)遇到输入/输出错误”时可能会发生这种情况

究竟是什么原因导致仅为读取而打开的文件描述符的
close(2)
失败并出现错误
EIO
?显然,这不是一个未提交的
写入(2)
。在这个特定的文件中,它是使用Android的DownloadManager服务下载的,这意味着可能会有线程和/或进程试图同时访问它,但我几乎看不出这会如何影响关闭它。此外,在代码运行()之后,该文件即将被删除,但除非Android中有一个未记录的时间机器,否则未来的代码不应该在这里产生影响


我对Android和/或Linux上的答案特别感兴趣,但如果能为其他操作系统提供更一般的答案,我将不胜感激。

一般来说,在关闭流时,您应该始终预测IOException。代码非常简单,但请参见此处,以获取Java能够提供的最干净的示例:

但是,在您的特定情况下,我认为会引发异常,因为您似乎正在更改unzipOrPassthrough(InputStream)方法中InputStream的值,然后稍后尝试关闭它:

        if (entry == null) {
        is = new ByteArrayInputStream(baos.toByteArray());

稍后在FileInputStream类上调用close时,它可能会崩溃,因为它现在是ByteArrayInputStream,不再是FileInputStream。

我猜
EIO
来自
fs/bad\u inode.c
中的
bad\u file\u flush
。当内核在访问inode时出现任何故障时,它会将打开的文件描述转换为一个伪打开的文件,并将
bad\u inode\u ops
作为其文件ops。我找不到用于基于FAT的文件系统的代码,但可能有一些通用代码


至于原因,可能是连接USB电缆,从连接的计算机上安装文件系统,卸下SD卡等等。

我走不了多远,因为我不知道
c
posix
系统。相关问答。
libcore.io
close
native
实现(用于fd)的源代码。在最后一个链接中,您必须在第429行找到
close()
的实现。@SotiriosDelimanolis:是的,我看到了在
EIO
错误后讨论文件描述符状态的问题;我感兴趣的是什么导致了
EIO
,而不是错误发生后该怎么办。
close()
的实现是Linux内核内部的一个系统调用。它似乎与一个坏的inode有关,但是挖掘内核代码所花费的时间比我想象的要长一点……这里也一样。我不认为
close
可以通过
EIO
返回任何方法,除了外来的文件系统。有问题的文件是什么文件系统类型的?它甚至没有意义。如果它现在是一个
ByteArrayInputStream
对象,他就不能“以后调用
FileInputStream
类上的close”。他正在通过tearrayinputstream关闭
。时期关于“现在是一个
ByteArrayInputStream
而不再是一个
FileInputStream
的部分是毫无意义的。引用的类型为
InputStream。
对对象的引用无法记住它们指向的对象的类型。
unzipOrPassthrough()
读取传入的输入流,但不会关闭它。它确实重新分配了本地参数
is
,但这对传入的原始流没有影响。不幸的是,我无法访问用户的设备,因此我无法确定到底发生了什么,但在此之前,这似乎是最有可能的解释。在浏览内核源代码一段时间后,似乎
sys\u close()
只能返回0、
-EINTR
-EBADF
,或者文件系统
flush()
实现的返回值,
vfat
没有实现
flush()