2016-06-15 9 views
1

私は4GBを超えるメインフレームのデータファイルを持っています。 500バイトごとにデータを読み込んで処理する必要があります。私はあなたが解決策で私を助けることができるしかし私にInteger.MAX_VALUEがファイルを読み込む> Javaで4GBのファイル

public void getFileContent(String fileName) { 
    RandomAccessFile aFile = null; 
    FileChannel inChannel = null; 
    try { 
     aFile = new RandomAccessFile(Paths.get(fileName).toFile(), "r"); 
     inChannel = aFile.getChannel(); 
     ByteBuffer buffer = ByteBuffer.allocate(500 * 100000); 
     while (inChannel.read(buffer) > 0) { 
      buffer.flip(); 
      for (int i = 0; i < buffer.limit(); i++) { 
       byte[] data = new byte[500]; 
       buffer.get(data); 
       processData(new String(data)); 
       buffer.clear(); 
      } 
     } 
    } catch (Exception ex) { 
     // TODO 
    } finally { 
     try { 
      inChannel.close(); 
      aFile.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

を超えたメッセージでエラーを取得しています、のFileChannelを使用してみましたが?

+4

例外とスタックトレースを表示 – assylias

+0

'FileInputStream'を' BufferedInputStream'でラップすることができます。 – venture

+2

これをチェックしてください - > http://stackoverflow.com/questions/8076472/why-does-filechannel-map-take-up-to-integer-max-value-of-data – Techidiot

答えて

2

あなたのコードの最悪の問題は、あなたがあなたのコードによってスローされた例外を気付かないであろうことを意味し

catch (Exception ex) { 
    // TODO 
} 

一部です。 JREには「Integer.Max_VALUE超過」というメッセージは表示されないので、その問題はprocessDataメソッドに接続する必要があります。

このメソッドは繰り返しデータで頻繁に呼び出されることに注意してください。

あなたのループ

for (int i = 0; i < buffer.limit(); i++) { 

バッファ内のバイトが500 * 100000倍まで、があるとして、あなたは何度でも繰り返すことを意味します。それぞれの反復でバッファから500バイトを抽出して、各readの後に合計で500 * 500 * 100000バイトを処理しますが、ループ本体の末尾に間違ってbuffer.clear();が配置されているため、BufferUnderflowExceptionは発生しません。代わりに、500 * 100000回までのそれぞれprocessDataを、最初の500バイトのバッファで呼び出します。

しかし、バイトからStringへの全変換は不必要に冗長であり、不要なコピー操作を含んでいます。これを自分で実装する代わりに、Readerを使用してください。

さらに、あなたのコードは奇妙な迂回路になります。 Java 7 API Paths.getで始まり、それを従来のFileオブジェクトに変換するには、RandomAccessFileを作成して最終的にFileChannelを取得します。 Pathがあり、FileChannelが必要な場合は、直接FileChannel.openで開く必要があります。もちろん、適切な終了を確実にするためにtry(…) { … }ステートメントを使用してください。

しかし、あなたはString sと内容を処理したい場合、あなたは確かに代わりReaderを使用したい、言ったように:

public void getFileContent(String fileName) { 
    try(Reader reader=Files.newBufferedReader(Paths.get(fileName))) { 
     CharBuffer buffer = CharBuffer.allocate(500 * 100000); 
     while(reader.read(buffer) > 0) { 
      buffer.flip(); 
      while(buffer.remaining()>500) { 
       processData(buffer.slice().limit(500).toString()); 
       buffer.position(buffer.position()+500); 
      } 
      buffer.compact(); 
     } 
     // there might be a remaining chunk of less than 500 characters 
     if(buffer.position()>0) { 
      processData(buffer.flip().toString()); 
     } 
    } catch(Exception ex) { 
     // the *minimum* to do: 
     ex.printStackTrace(); 
     // TODO real exception handling 
    } 
} 

処理ファイル> 4ギガバイトに問題がない、私はちょうどそれをテスト8GBファイル。上のコードはUTF-8エンコーディングを使用しています。お使いのシステムのデフォルトエンコーディングであることを起こるものは何でも使ってのあなたの元のコードの動作を保持したい場合は、代わりに

Files.newBufferedReader(Paths.get(fileName), Charset.defaultCharset()) 

使用Readerを作成することができます。

関連する問題