2012-03-29 13 views
0

非常に大きなファイルを別の非常に大きなファイルに書き込もうとしています。私はfilechannelの書き込み行にこのエラーを受け取りました。なぜ私は分かりません。私はそれがデータ型の限界から外れていたからだと思っていましたが、長くても9,223,372,036,854,775,807まで上がり、最大で5,372,896,745にしかなりませんでした。これがなぜ起こっているのでしょうか? MappedByteBufferにはいくつかの制限がありますか?これは小さなファイルでは発生せず、Javaデスクトップアプリケーションで同じコードを使用しても問題は発生しません。 (Androidのみ)Android NIO - java.io.IOException:定義されたデータ型の値が大きすぎます

File f1 = new File(filename1); 

FileChannel fic, foc; 
long fsize; 
MappedByteBuffer mBUf; 

FileOutputStream out = new FileOutputStream(f1,true); 
foc = out.getChannel(); 

File f2 = new File(filename2); 
FileInputStream in = new FileInputStream(f2); 

fic = in.getChannel(); 
fsize = fic.size(); 

for (long b = 0; b < fsize; b += 65536) 
{ 
    if (fsize - b < Resource.MEMORY_ALLOC_SIZE) 
     mBUf = fic.map(FileChannel.MapMode.READ_ONLY, b, fsize - b); 
    else 
     mBUf = fic.map(FileChannel.MapMode.READ_ONLY, b, Resource.MEMORY_ALLOC_SIZE); 
    foc.write(mBUf); //ERROR HERE! 
}    

fic.close(); 
in.close(); 
foc.close(); 
out.close(); 

アイデア/ご意見はありがとうございます!

答えて

3

れるMappedByteBufferが持っているいくつかの制限はありますか?もちろん

あります。利用可能な仮想メモリは開始時に制限され、その後は仮想アドレス空間によって制限されます。

このタスクでは、MappedByteBuffers,ではなく、transferTo()を使用する必要があります。これは、後者が占有する仮想アドレス空間を廃棄する合意の手段がないためです。

+0

代わりにtransferToルートを試みましたが、それでも同じエラーが発生していました。 – azdragon2

+1

@ azdragon2転送サイズを小さくする必要があります。約1メガバイト以上を指定する利点はありません。 'transferTo()' APIの構造によって、要求された量を転送することを保証しないので、とにかくそれをループに入れなければなりません。だからそれを行い、 'サイズ'パラメータを何かに調和させる。 – EJP

-1

残念ながら、ロングは(私はそれが4GBのRAM上で持っていないので、Androidはあると信じて)32ビットシステム上でその高行きません。したがって、Androidの署名されていないlongの最大長は4,294,967,295です。これは、あなたの限界を超えていることを意味します。

+0

エラーが発生しているforループのデータ型が長いとは思いませんが、正しいパスで私を送ってくれました。 2097215 KBまたは〜2.00006 GBのファイル用のチャンネルには、このエラーが発生しているようです。私はいつもNIOがファイル全体をメモリにロードしていないという印象を受けましたか?代替パスを検索する必要があります。助けてくれてありがとう! – azdragon2

+0

@ azdragon2 'MappedByteBuffer' *はファイル全体をメモリにマップします。 Javadocを参照してください。あなたはそれをしたくありません! – EJP

+2

32ビットシステムでは 'Long' *が確実に*高くなります。 'long'のサイズはアーキテクチャに依存しません。 NIOの実装には限界があるかもしれませんが、* longのサイズ自体はAndroid上では何も異なるわけではありません。 –

関連する問題