我正在调查一个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();
}
}
完整的源代码可以在GitHub上找到。
异常是从
fis.close()
这一行抛出的。从我阅读Android源码得知,看起来FileInputStream.close()
对本地代码中的底层文件描述符只是调用了close(2)
。手册似乎没有说明什么会导致
EIO
错误,它们只是说“发生了I/O错误”或者“如果在关闭()期间从文件系统读取或写入时发生了I/O错误”。Mac OS X的手册说它可能发生在“以前未提交的write(2)遇到输入/输出错误。”的情况下。在这些系统中,该错误可能是由于内存问题等原因引起的。像本例中仅打开文件进行读取的文件描述符,究竟是什么原因导致
close(2)
失败并显示EIO
错误?显然不是未提交的write(2)
。对于这个特定文件,它是使用Android的DownloadManager服务下载的,这意味着可能有残留的线程和/或进程同时访问它,但我几乎无法想象这会影响关闭文件。此外,在此代码运行之后,文件将被删除(此处),但除非Android有未记录的时间机器,否则未来的代码不应在这里产生影响。我特别感兴趣的是Android和/或Linux的答案,但对其他操作系统的一般答案也将受到欢迎。
c
或posix
系统。相关问题和答案在这里。libcore.io
的源代码在这里,close
(用于fd)的native
实现在这里。 - Sotirios Delimanolisclose()
的实现。 - Sotirios DelimanolisEIO
错误后文件描述符的状态;我对导致EIO
的原因感兴趣,而不是在错误发生后该怎么做。close()
的实现是Linux内核中的系统调用。 - Adam Rosenfieldclose
会返回EIO
的其他方式。你所说的文件所处的文件系统类型是什么? - R.. GitHub STOP HELPING ICEvfat
(根据mount(1)
),所以我怀疑用户的SD卡也可能是这种格式。 - Adam Rosenfield