5

大きなファイル (100 MB) を含むByteBufferがあります。

    java.nio.ByteBuffer byteBuffer = ByteBuffer.wrap(multipartFile.getBytes());
    writeChannel.write(byteBuffer);
    writeChannel.closeFinally();

一度に合法的に書き込むことができるのは 1 MB だけwriteChannelです。

ByteBuffer の内容をスライスして、一度に 1 MB のスライスだけを に書き込むにはどうすればよいwriteChannelですか?

4

2 に答える 2

11

を使用ByteBuffer#slice()してベース インスタンスの複製ビューを取得しByteBuffer、位置を移動してコンテンツのスライド ウィンドウを表示できます。別の方法として、ベース バッファーを他のコンシューマーに公開する必要がない場合は、ベース バッファーに対して同じことを行うこともできます。

コンテンツのビューの開始位置は単一引数Buffer#position(int)メソッドで変更でき、ビューの終了位置は で変更できますBuffer#limit(int)。基になるバッファーの制限を超えてビューをプッシュしないように注意している限り、次のことができます。

final ByteBuffer view = base.slice();
for (int start = base.position(), end = base.limit(), stride = 1000000;
     start != end;
     start = view.limit())
  consume(view.position(start)
              .limit(start + Math.min(end - start, stride)));

私はそれをテストしませんでしたが、それ正しいようです。ここでは厳密には必要ではありませんが、位置の初期設定を回避するために書き直すことは可能ですが、繰り返しが発生するか、最初からより扱いにくい特殊なケースの処理が発生します。

基本的なfor ループ構造を維持するために、このままにしました。

于 2011-07-04T23:03:17.667 に答える
0

私の知る限り、writeChannel(私が推測した名前はSocketChannelタイプであると思われる)のwrite()は、「最大rバイトをチャネルに書き込もうとします。ここで、rはバッファに残っているバイト数です。つまり、dst.remaining()、このメソッドが呼び出された時点で". (これによる

ByteBuffer.remaining()の説明では、このメソッドは「現在の位置と制限の間の要素の数を返す」と述べています。

したがって、私の推測では、ByteBuffer 全体を記述できないということではなく、コードで ByteBuffer オブジェクトに対して flip() を呼び出す必要があるため、次のようになります。

java.nio.ByteBuffer byteBuffer = ByteBuffer.wrap(multipartFile.getBytes());
byteBuffer.flip();
writeChannel.write(byteBuffer);
writeChannel.closeFinally();

Buffer.flip()で述べられているように、「一連のチャネル読み取りまたは書き込み操作の後、このメソッドを呼び出して、一連のチャネル書き込みまたは相対取得操作の準備をします」

于 2011-07-04T22:54:24.397 に答える