2016-12-19 13 views
0

大きなファイルセット(それぞれ約2〜3GB)があり、それを読み取ってその一部を新しいファイルに出力するにはInputStreamを使用する必要があります。InputStreamファイルと出力の一部を読み取る

//this is just for example 
int size=100; 
String src="pathtofile"; 
OutputStream os = null; 
Inputstream is = new FileInputStream(new File(src)); 
byte[] buffer = new byte[size]; 
byte[] bufferis = getBytesFromIS(is); 

buffer=Arrays.copyOfRange(bufferis,0,buffer.length); 

String tempstr=new String(buffer); 
byte[] tempBytes=Arrays.copyOfRange(bufferis, buffer.length,is.available()); 
os = new FileOutputStream(new File(dest)); 
copy(new ByteArrayInputStream(tempBytes), os); //function writing to file 

これは小さなファイルで正常に動作しますが、大きなファイルで使用しているとき、私はまだOutOfMemoryErrorを取得し、-Xmx6114mを設定した場合でも、OutOfMemoryErrorを得続けます。

+0

2GBのデータを扱うことができるプリントライターを試してみてください.... – SmashCode

+0

ここでの答えは非常に簡単です。ファイルの一部しか必要としない場合は、ファイル全体を読み取らないでください! 'InputStream'を使う理由はありますか?ストリームはしばしばより汎用性がありますが、この特定のユースケースは 'RandomAccessFile'でもっと簡単に解決できます。 – Marco13

+0

' bufferis'を削除する必要があります。あなたは 'int bytesRead = is.read(buffer);' – roby

答えて

0

最大配列長は、Integer.MAX_VALUEよりわずかに小さく、約2e9である。だから、全体をbyte[]に読み込むことができず、何か別のものを使わなければなりません。おそらくByteByfferが最も速い解決策(メモリマップされたファイル)でしょう。

+0

この場合、inputstreamをbytebufferにどのように読み込むのですか? – user2324644

+0

@ user2324644 https://docs.oracle.com/javase/8/docs/api/java/nio/channels/FileChannel.html#map-java.nio.channels.FileChannel.MapMode-long-long- – maaartinus

+0

バイトバッファでは、まだ3GB以上のファイルサイズを処理できません。 – user2324644

1

あなたはgetBytesFromIS(is)を表示しませんが、ファイル全体を読み込むと仮定すると、それは必要ありません。

最も簡単な方法は、すでにこの機能を提供しており、十分にテストされたライブラリを使用することです。たとえば、Apache Commons IOUtilsとなります。

それ以外の場合は、オフセット0から目的の長さで始まるInputStream.read(b, off, len)を使用できます。 しかし、この機能は、ではなく、で、必要なデータ量をすべて読み取ることが保証されています。

+0

IOUtilsを使用して、ファイルinputstreamはまだバイトバッファに読み込まれるので、私は間違っていない場合はメモリエラーになるだろうと仮定します – user2324644

+0

IOUtils .toByteArray(inputstream)これはまだサイズの問題のために動作しません。 – user2324644

+0

@ user2324644 - 'IOUtils.toByteArray(inputstream)'はリンク内の関数ではありません。 – kdgregory

関連する問題