2015-11-22 46 views
3

我正在考慮使用Java NIO來處理文件並使用解碼器功能來處理不同的字符集。我擔心的是,如果解碼器一開始就試圖讀取整個文件,這可能會導致效率或內存問題。例如,給定以下代碼(爲清楚起見省略異常處理程序):使用NIO解碼器會導致整個文件被讀取嗎?

Charset charset = Charset.forName("ISO-8859-15"); 
CharsetDecoder decoder = charset.newDecoder(); 
FileInputStream fis = new FileInputStream(file); 
FileChannel fc = fis.getChannel(); 
int lenFile = (int)fc.size(); 
MappedByteBuffer bufferFile = fc.map(FileChannel.MapMode.READ_ONLY, 0, lenFile); 
CharBuffer cb = decoder.decode(bufferFile); // <--- possible problem here 
// process character buffer 
fc.close(); 

在線,其中的CharBuffer創建我的關心的是,解碼器將建立一個緩衝器包含整個文件,它可以是千兆字節大小,從而導致內存問題。它是否嘗試創建一個文件大小的緩衝區?有沒有辦法控制緩衝區的大小?

+0

你已經映射了整個文件並解碼了整個映射的緩衝區,所以當然你會得到另一個與文件大小相同的緩衝區。但是,如果文件是千兆字節,則不應將其映射到第一位。 – EJP

+0

那麼,什麼是正確的方式來解碼一個潛在的大文件,而不必擔心內存問題? –

回答

0

它並沒有真正讀取文件,而是將其映射到內存中。這意味着文件的各個部分按需讀取,然後在操作系統意識到它未被訪問一段時間後丟棄。

但是它爲輸出分配了巨大的CharBuffer,因爲這基本上是處理結果。

在這裏,我會考慮實現簡單的while循環 - 讀取字節,調用解碼,刷新當前輸出並重復,直到到達文件結尾。

+0

這似乎有道理。但是,如果在解碼字符之前將字符讀入緩衝區,那麼如何防止緩衝區意外地分裂多字節字符?另外,不會有一個問題,因爲Unicode或UTF-8字符串需要某種類型的前導碼,它將在第一次讀取緩衝區時出現,但是後續的一次沒有? –

+0

CharsetDecoder在讀取部分輸入時保持其狀態。勾選[文件](http://docs.oracle.com/javase/7/docs/api/java/nio/charset/CharsetDecoder.html#decode(java.nio.ByteBuffer中,%20java.nio.CharBuffer,% 20boolean)),特別是'endOfInput'參數。 –

相關問題