2014-09-29 194 views
2

我正在嘗試從InputStream中讀取。我寫下面的代碼如何決定從輸入流中讀取多少個字節?

byte[] bytes = new byte[1024 * 32]; 
       while (bufferedInStream.read(bytes) != -1) { 
        bufferedOutStream.write(bytes); 
       } 

我不明白的是我應該讀一遍迭代多少字節?該流包含保存在磁盤上的文件。

我讀here但我真的不明白這個帖子。

+0

據我所知,你引用的文章說如果你從磁盤讀取,你可以使用從8 KB到64 KB。如果您的文件大小小於64 KB,則可以通過一次迭代或最多兩次讀取它。 – GokcenG 2014-09-29 08:58:35

+0

使用緩衝區的原因是它比一次讀取一個字節更快。這是一個有效的緩衝區大小,取決於您要複製的內容,即它是套接字或文件還是USB。 512字節和64 KB之間的大小往往是有效的。例如大於1 MB的大小可能會比較小的緩衝區慢。 – 2014-09-29 13:28:39

回答

2

假設您有水從管道流入洗澡。然後,你用一個水桶從浴缸裏取水,然後帶着說你的花園給草坪澆水。浴是緩衝區。當你在草坪上行走時,緩衝器已經填滿了,所以當你回來的時候,有一個桶可供你再次使用。

如果浴缸很小,那麼當你用水桶行走時它會溢出,所以你會失水。如果你有一個巨大的沐浴,那麼它不可能溢出。所以更大的緩衝區更方便。但當然一個更大的浴缸需要更多的錢並佔用更多的空間。

程序中的緩衝區佔用內存空間。你不想爲你的緩衝區佔用所有可用的內存,只是因爲它很方便。

通常在讀取功能中,您可以指定要讀取的字節數。所以,即使你有一個小的緩衝區,你可以做到這一點(僞):

const int bufsize = 50; 
buf[bufsize]; 
unsigned read; 
while ((read = is.read(buf, bufsize)) != NULL) { 
    // do something with data - up to read bytes 
} 

在上面的代碼中bufzise是讀入緩衝區最大數據。

如果您的讀取函數不允許您指定要讀取的最大字節數,那麼您需要提供足夠大的緩衝區以獲得儘可能大的讀取量。

所以最佳緩衝區大小是特定於應用程序的。只有應用程序開發人員會知道數據的特徵。例如,水流入浴池的速度有多快。你能買得起什麼浴缸尺寸(嵌入式應用程序),你可以多快地從花園裏洗澡,然後再回來。

+1

當讀取文件的結尾或從套接字讀取時,讀取的大小大部分時間都不匹配緩衝區。即你不能忽視它。 – 2014-09-29 13:26:23

+1

@PeterLawrey真的,我沒有太嚴格的僞代碼,我加了一個讀數 - 這可能是有益的。 – 2014-09-29 14:06:30

0

基本上,你有你指定(1024 * 32)

然後長度的字節容器,InputStream的會,直到它到達的填充的結束儘可能,可能是全容器,迭代整個迭代文件時,它將會只填寫剩餘的字節,並返回-1下一個循環(一個它不能讀取任何東西)

所以你基本上是從輸入複製粘貼&輸出1024 * 32字節大小的塊

希望它能幫助你理解代碼

順便說一句,最後一次迭代,如果輸入流少於1024 * 32,輸出將不僅接收文件的最後部分,而且還會重複先前的迭代內容最後一次迭代。

0

這個想法並不是一次使用緩衝輸入流來讀取整個文件內容。您使用緩衝輸入流來讀取與bytes []數組大小相同數量的字節。您使用讀取的字節,然後繼續讀取文件中的更多字節。因此,您不需要知道文件大小就可以讀取它。

這篇文章會更有幫助,因爲它解釋了爲什麼你應該換一個FileInputStream一個緩衝的輸入流

Why is using BufferedInputStream to read a file byte by byte faster than using FileInputStream?

4

這取決於可用內存,文件大小和其他東西。你最好做一些測量。

PS:你的代碼是錯誤的。 bufferedInStream.read(bytes)可能無法填滿所有緩衝區?但只是其中的一部分。該方法返回實際的字節數作爲結果。

byte[] bytes = new byte[1024 * 32]; 
int size; 
while ((size = bufferedInStream.read(bytes)) != -1) { 
    bufferedOutStream.write(bytes, 0, size); 
}