2013-08-04 38 views
7

我一直在使用流很多次,但我從來沒有讀過很多關於他們如何實際工作。除了流只是一個比喻之外,我對它們的瞭解也不多。一個流只代表一個字節序列。我不太瞭解他們是如何實際工作的,我猜想在Java中打開一個文件流與具有向流提供「指針」的功能的操作系統交互。Java中的流如何影響內存消耗?

基本上我的問題是流如何影響內存消耗。例如,當你有一個輸入流,然後你開始讀取它時,你只能通過讀取的字節數來增加內存消耗?在Java中打開流時,在開始閱讀之前實際上並未加載完整文件?如果您從一個流中讀取數據並直接寫入另一個數據流,則只會增加讀取的字節數量(並且可能在緩衝區中)?如果你在java中將字節讀入一個字節數組,那麼你會增加文件大小的內存消耗?

可能聽起來像一個奇怪的問題,但我可能需要一些指導/更正我的理解。謝謝。

+0

你有一個非常好的解釋[這裏](http://www.ibm.com/developerworks/library/j-zerocopy/index.html)零拷貝。還解釋了緩衝區和內存使用情況。 –

回答

3

InputStream開始閱讀後,幾乎沒有內存開銷。有一個非常小的操作系統開銷打開一個文件和JVM的一個小開銷用於新的對象分配。如果使用默認值爲8KB的BufferedInputStream,則可能會有小的開銷。

寫入的開銷非常大,取決於您寫入的位置。如果它是FileOutputStream,那麼它與上面描述的相同。如果是ByteArrayOutputStream,那麼在最壞的情況下,最好是(2 * stream length)字節和(3 * stream length)字節。即將InputStream中的10k字節複製到字節數組中,最差情況下將分配30k字節。

原因是ByteArrayOutputStream尺寸在達到限制後增長了2倍,並且在您撥打toByteArray()時還會分配一個新的緩衝區。

5

以上所有答案都是很好的答案,但我不相信他們回答你關於內存消耗的原始問題。

在Java中,您可以通過多種方式查看流。首先,您擁有最低級別流的原始流,並以最小的內存開銷與底層操作系統(文件,網絡等)進行交互。其次是緩衝流,可用於包裝原始流並添加一些緩衝並顯着提高性能。流緩衝會爲緩衝添加固定數量的內存開銷,並可由應用程序進行設置。不知道默認是什麼,但它可能是最小的,如32K。

第三種類型的流是一種內存流(即ByteArrayInput/Ouput),它們使用盡可能多的內存來寫入它們,並且將根據需要增長並且不會丟棄它們的內存,直到引用計數變爲零(它們是不再使用)。這些流非常有用,但顯然會消耗大量內存。

最終的類型實際上不是一個流,而是一類被稱爲讀者的I/O,它提供了上面指出的向數據流和從數據流中提供數據轉換的幫助。這些流操作在一個原始的。緩衝或內存流,並將消耗與正在使用的基礎流一樣多的內存。