簡體   English   中英

在Java中,當我調用OutputStream.close()時,我是否總是需要先調用OutputStream.flush()?

[英]In Java, when I call OutputStream.close() do I always need to call OutputStream.flush() before?

如果我只是在輸出流中調用close() ,輸出是有保證的,還是需要我總是調用flush()

雖然close應該調用flush ,但它比那復雜一點......

首先,裝飾器(例如BufferedOutputStream )在Java中很常見。 裝飾器的構造可能會失敗,因此您需要close finally塊中的“原始”流,其中try包含裝飾器。 在異常的情況下,您通常不需要close裝飾器(例如,對於嚴重實現的壓縮裝飾器除外)。 您通常需要在非異常情況下flush裝飾器。 因此:

final RawOutputStream rawOut = new RawOutputStream(rawThing);
try {
    final DecoratedOutputStream out = new DecoratedOutputStream(rawOut);
    // ... stuff with out within ...
    out.flush();
} finally {
    rawOut.close();
}

最重要的是,裝飾器close方法通常不正確地實現。 這包括java.io一些直到最近。

當然,你可能想要使用Execute Around習語來保持DRY(ish)。

關閉()總是刷新,所以不需要打電話。

編輯:這個答案是基於常識和我遇到的所有輸出流。 誰將為緩沖流實現close()而不先刷新緩沖區? 在close()之前調用flush是沒有害處的。 但是,如果過度調用flush()會產生后果。 它可能會在緩沖機制下失敗。

這里有很多危險的答案和評論。 繼續閱讀為什么我使用危險這個詞。

首先要做的事情。 看看這些。

你會發現沒有一個聲明說close()會調用flush() 如果我錯過了任何修理我。

每當需要或需要保證至少刷新到OS級別的緩沖數據時,請使用flush()

flush()有自己的目的。

// client
// sends exactly 234 bytes
// and returns exactly 124 bytes from the server
static byte[] sendAndReceive(final OutputStream output,
                             final InputStream input)
    throws IOException {
    final byte[] request = new byte[234];
    output.write(request);
    // output.flush(); // @@? is this required or not?
    final byte[] response = new byte[124];
    new DataInputStream(input).readFully(response);
    return response;
}

// server
// recieve exactly 234 bytes from the client
// sends exactly 124 bytes
static void receiveAndSend(final InputStream input,
                           final OutputStream output)
    throws IOException {
    final byte[] request = new byte[234];
    new DataInputStream(input).readFully(request);
    final byte[] response = new byte[124];
    output.write(response);
    // output.flush(); // @@? is this required or not?
}

事情可能已經發生了變化,但十年前我自己也經歷過這種情況。 上面的源代碼(客戶端)與Windows XP一起使用,並且在Windows 2000 Server中用於同一端點(服務器)失敗。

並且(你)不必(必須)依賴close()任何特定於實現的行為。

static void writeFile(File file, byte[] bytes) throws IOException {
    try (OutputStream out = new FileOutputStream(bytes)) {
        out.write(bytes);
        out.flush(); // who cares what FileInputStream#close does?
    }
}

另請注意, flush()並不意味着將數據寫入/發送到物理磁盤或遠程端點。 它主要是將JVM中的緩沖數據刷新到底層操作系統中。


勘誤表

Writer#close()明確地說出來了

關閉流,先沖洗它。

但這並不意味着所有子類都保留此根合同。 請參閱PrintWriter#close() ,其中(不使用flush() )關閉內部outWriter ),再次依賴於outclose()實現。

如果你想要刷新流,那么是的 ,在調用close()之前調用flush() close()

盡管所有其他相反的答案(但在一些評論中正確指出), java.io.OutputStream::close()的默認實現不會調用flush() 事實上,它什么都不做。 如果您有源代碼分發,您可以自己輕松檢查它,否則只需信任官方的javadoc ,引用到這里:

close的一般合同是它關閉輸出流。 封閉流無法執行輸出操作,無法重新打開。

OutputStream的close方法什么都不做。

無論close()是否刷新,最安全的方法應該是手動沖洗它。 如果它再次被沖洗,誰在乎呢?

“Tom Hawtin - tackline”的答案有關於安全關閉流的其他細節(但並沒有真正回答原來的問題= P)。

暫無
暫無

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

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