簡體   English   中英

close是否會拋出IOException?

[英]Does close ever throw an IOException?

在這里提供了一些答案並閱讀了一些注釋后,似乎實際上IOException永遠不會在文件I / O上關閉。

是否有任何情況下,在Stream / Reader / Writer上調用close實際上會拋出IOException?

如果實際拋出異常,應如何處理?

我發現了兩個案例:

  • 當要刷新的緩沖區中仍有數據時丟失網絡連接。
  • 當緩沖區中仍有數據要刷新時,讓文件系統填滿(或達到文件大小的用戶限制)。

這兩個示例都依賴於緩沖區中仍有數據時發生的事情。 在文件關閉之前關閉刷新緩沖區,因此如果將數據寫入文件時出錯,則會拋出IOException。

如果執行以下代碼,將其傳遞給要在網絡驅動器上創建的文件的名稱,然后在按Enter鍵之前拔下網絡電纜,則會導致程序在關閉時拋出IOException。

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class Test
{
    public static void main(final String[] argv)
    {
        final File file;

        file = new File(argv[0]);
        process(file);
    }

    private static void process(final File file)
    {
        Writer writer;

        writer = null;

        try
        {
            writer = new FileWriter(file);
            writer.write('a');
        }
        catch(final IOException ex)
        {
            System.err.println("error opening file: " + file.getAbsolutePath());
        }
        finally
        {
            if(writer != null)
            {
                try
                {
                    try
                    {
                        System.out.println("Please press enter");
                        System.in.read();
                    }
                    catch(IOException ex)
                    {
                        System.err.println("error reading from the keyboard");
                    }

                    writer.close();
                }
                catch(final IOException ex)
                {
                    System.err.println("See it can be thrown!");
                }
            }
        }
    }
}

從Java 7開始,您可以使用try-with-resources來擺脫這種混亂(刪除了close()操作的顯式異常生成代碼):

private static void process(final File file) {
    try (final Writer writer = new FileWriter(file)) {
        writer.write('a');
    } catch (final IOException e) {
        // handle exception
    }
}

這將自動神奇地處理close()的異常,並在內部執行顯式null檢查。

當它確實發生時,它應該像任何其他IOException一樣處理,而不是像你經常看到推薦那樣默默地被忽略。 我猜這個假設是,既然你已經完成了使用流,那么它是否被正確清理並不重要。

但是,正確清理很重要。 如果close()操作確實引發異常,則可能是它涉及刷新某些輸出,提交某些事務(在數據庫連接的情況下,您認為是只讀的)等等 - 絕對不應該忽略。 而且,由於這種情況很少見,因此您不會通過中止操作來顯着降低應用程序的可靠性。

對於文件,您可能看不到在close()上經常拋出的IOException,但您肯定會看到非文件I / O,如關閉網絡套接字。

下面是一個Java錯誤示例 ,其中關閉UDP套接字最終導致拋出IOException。

它特別是FileInputStream.close ,它不會拋出,即使你的硬盤驅動器着火了。 據推測,套接字輸入是一樣的。 對於輸出流,您也可能正在刷新。 直到最近[查看時間戳] BufferedOutputStream用於在flush拋出時無法關閉底層流。

(@MaartenBodewes希望我指出API文檔沒有指定不拋出的FileInputStream.close 。在帖子發布時,通常會忽略提及這與Sun JDK(現在稱為Oracle JDK)相關的條款看起來,Android曾經使用的一個名為Apache Harmony的模糊的前重新實現可能有不同的行為。可能還有其他實現,或OpenJDK的版本,也可能拋出。)

檢查調用close時會發生什么,異常隱藏如何影響你以及你可以做些什么: 博客文章

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM