3

IOExceptionファイルを閉じられなかったために がスローされる Android の問題を調査しています。

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 エラーが発生しました」などと書かれているだけです。または「close()中にファイルシステムからの読み取りまたはファイルシステムへの書き込み中にI / Oエラーが発生した場合」。Mac OS X のマニュアル ページには、「以前にコミットされていない書き込み (2) で入出力エラーが発生した」場合に発生する可能性があると記載されています。それらのシステムで。

この場合のように、読み取り専用に開かれたファイル記述子close(2)のエラーで失敗する正確な原因は何ですか? EIO明らかに、それは uncommitted ではありませんwrite(2)。この特定のファイルの場合、Android の DownloadManager サービスを使用してダウンロードされました。つまり、同時にアクセスしようとしているスレッドやプロセスが残っている可能性がありますが、それがファイルを閉じようとするとどのように影響するかはほとんどわかりません。また、このコードが実行された後、ファイルは削除されようとしています (こちら) が、Android に文書化されていないタイム マシンが含まれていない限り、将来のコードはここに影響を与えるべきではありません。

特に Android や Linux での回答に興味がありますが、他の OS でのより一般的な回答もいただければ幸いです。

4

2 に答える 2

3

EIOから来てbad_file_flushいると思いfs/bad_inode.cます。bad_inode_opsカーネルが i ノードへのアクセスに失敗した場合、開いているファイルの説明をそのファイル ops としての疑似オープン ファイルに変換するようです。FAT ベースのファイルシステムでこれを行うコードは見つかりませんが、おそらく一般的なコードがいくつかあるでしょう。

理由としては、おそらくUSBケーブルを接続して、接続されたコンピュータからファイルシステムをマウントしたり、SDカードを取り外したりすることなどです。

于 2013-09-10T00:43:38.877 に答える
-1

一般に、ストリームを閉じるときは常に IOExceptions を予測する必要があります。コードは非常に簡単ですが、Java が提供できる最もクリーンな例については、こちらを参照してください。

https://stackoverflow.com/a/156520/1489860

ただし、特定のケースでは、 unzipOrPassthrough(InputStream)メソッドでInputStream の値を変更し、後でそれを閉じようとしているように見えるため、例外がスローされていると思います。

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

後で FileInputStream クラスで close を呼び出すと、FileInputStream ではなく ByteArrayInputStream になっているため、おそらくびっくりします。

于 2013-09-10T00:05:19.093 に答える