2012-11-26 49 views
0

記憶的我有一個非常大的ByteBuffer是大小約幾MB。當我在退房charset編碼

FileChannel fc = new FileInputStream(new File(decodedUri)).getChannel(); 
ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); 
CharBuffer cb; 
if (encoding == null) 
    encoding = "UTF-8"; 
cb = Charset.forName(encoding).decode(bb); 

運行ByteBuffer我得到在堆棧跟蹤可以追溯到Charset.decode所有其他時間OutOfMemoryError。正是這條線觸發了錯誤。

cb = Charset.forName(encoding).decode(bb); 

我該如何解決這個問題?

因爲應用程序被啓動的OutOfMemoryError第一次沒有被觸發,只有我第二次試圖啓動它,會出現此錯誤。我想知道是否有某種衝出緩衝區我需要做的?或者類似的東西?

+0

你能請張貼堆棧跟蹤? – Isaac

+0

這將是相當困難的。這是一個Android txt閱讀應用程序,通過點擊txt文件即可開始。所以我無法在模擬器上測試它,但必須在Android手機上測試。 –

+0

@JasonChing - 你需要能夠訪問整個解碼文件一次?使用「CharsetDecoder」並從文件中讀取數據塊來提供它將允許您以增量方式處理文件。 – Jens

回答

2

如果你想讀的組塊巨大的文件,你可以像這樣做有AsyncTask

static class StreamTask extends AsyncTask<String, Void, Integer> { 
    private static final int BUFFER_LENGTH = 1024 * 8; // Adjust to taste 

    // Param #0 = file name 
    // Param #1 = charset name 
    @Override 
    protected Integer doInBackground(String... params) { 

     if (params.length != 2) { 
      throw new IllegalArgumentException(); 
     } 

     int chars = 0; 
     CharsetDecoder cd = Charset.forName(params[1]).newDecoder(); 
     try { 
      FileInputStream fin = new FileInputStream(params[0]); 
      try { 
       FileChannel fc = fin.getChannel(); 
       ByteBuffer bb = ByteBuffer.allocateDirect(BUFFER_LENGTH); 
       CharBuffer cb = CharBuffer.allocate(BUFFER_LENGTH); 

       while (fc.read(bb) != -1) { 
        // Flip the buffer, decode the contents 
        bb.flip(); 
        cd.decode(bb, cb, false); // You should probably look at CoderResult also. 
        // Flip & extract the decoded characters. 
        cb.flip(); 
        chars += cb.remaining(); 
        onCharacters(cb.array(), cb.position(), cb.remaining()); 
        cb.clear(); 
        // Prepare the buffer for reuse. 
        bb.compact(); 
       } 

       // fc.read(..) returned -1 -> EOF, but bb may still contain 
       // stuff to decode. 
       bb.flip(); 
       cd.decode(bb, cb, true); 
       cd.flush(cb); 
       cb.flip(); 
       if (cb.remaining() > 0) { 
        chars += cb.remaining(); 
        onCharacters(cb.array(), cb.position(), cb.remaining()); 
       } 
      } finally { 
       fin.close(); 
      } 

     } catch (IOException e) { 
      chars = -1; 
     } 
     return chars; 
    } 


    protected void onCharacters(char[] ch, int offset, int length) { 
     // Do something with the characters (still running in the AsyncTask thread) 
    } 
} 
+0

謝謝Jens!你能告訴我如何解碼ByteBuffer,比如說BIG5嗎? –

+0

嗯?這個例子會解碼你通過它的任何字符集,例如'新StreamTask()執行(「路徑/到/你/ big5textfile.txt」,「中文」);'你傳遞給'execute'第二個參數是字符集的名稱。 – Jens