JAVA NIOでのByteBuffer

3028 ワード

ByteBufferには主に以下の属性があります.
capacity
最大格納可能なByte数を示す容量サイズ
position
操作ポインタは、getやputを次回呼び出すとここから読み出され、言い換えればput/getごとにpositionが1回増加します.
limit
キャッシュ領域の「有効」を表す要素の長さ、例えばByteBufferの容量capacityが10に設定されている場合、この10バイトはデフォルトで0(数値なしを示す)であり、limitの役割は10バイトのうち何バイトが有効かを示す.buffer putに5バイト入るとlimitは5.
ByteBufferの主な方法
clear()--主に書き込みの準備をする前に呼び出すために使用されます.
Bufferの中のデータをクリアして、すべてのバイトをクリアして、limitを0に設定して、positionを0に設定して毎回bufferをいっぱい読むようにして、次を読む前にゼロにするべきで、bufferがいっぱいになったために読み続けることができません.ソース:
public final Buffer clear() {
        position = 0;
        limit = capacity;
        mark = -1;
        return this;
 }

flip()--主にputメソッドを呼び出してデータを書き終わった後に読み出す準備(getメソッドを呼び出す)に使用されます.
現在のposition位置を記録し(limitを変更して現在の有効バイト位置を記録する)、positionを0にクリアします.ソース:
public final Buffer flip() {
        limit = position;
        position = 0;
        mark = -1;
        return this;
}

reset()--主にbufferをループして読み込むためのデータ使用
現在のpositionポインタを、mark()メソッドが最後に呼び出されて記録された場所に移動します.たとえば、同じメッセージを異なるクライアントソースコードにブロードキャストします.
 public final Buffer reset() {
        int m = mark;
        if (m < 0)
            throw new InvalidMarkException();
        position = m;
        return this;
}

mark()--主にresetを準備する前に使用します.
現在のposition位置を記録し、次のresetを待つときにソースコードを使用します.
public final Buffer mark() {
        mark = position;
        return this;
}

bufferにputが1回データを完了すると、positionとlimitは同時に増加し、基本的に同期し、putが10バイトになった場合、positionとlimitは0から10に増加します.一方、positionは前述したようにgetやputの操作に用いられ、bufferへのputが完了した後、positionの設定を行わずに直接getを行うと、当然データは読み込めません.
remaining()
クエリーに現在どれだけの「有効」データが使用可能か、すなわちpositionとlimitの差を判断します.
サンプルコード:
コンソールの入力内容をループしてsocketに書き込む
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (true) {
   try {
           String s = reader.readLine();
           byte[] bytes = s.getBytes(utf8);
           buffer.clear();//    buffer       
           buffer.put(bytes);
           buffer.flip();//     buffer       ,      position  
           socketChannel.write(buffer);
       } catch (IOException e) {
           e.printStackTrace();
       }
}

初歩的に理解するために、このコードは基本的な使い方を簡単に示すだけで、実際にはbytesがbufferより大きい場合を考慮して、次のコードに変更します.
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (true) {
   try {
           String s = reader.readLine();
           byte[] bytes = s.getBytes(utf8);
           buffer.clear();
           for (int offset = 0; offset < bytes.length; offset++) {
                buffer.put(bytes[offset]);
                if (buffer.remaining() == 0) {
                     buffer.flip();
                     socketChannel.write(buffer);
                     buffer.clear();
                }
           }
    } catch (IOException e) {
       e.printStackTrace();
    }
}