バッファ(Buffer)


1、概念紹介


バッファ(Buffer)とは、I/Oのデータを一時的に記憶するためにメモリに指定されたサイズの記憶領域を予約するもので、この部分がバッファと呼ばれています.
バッファの使用には2つの利点があります.1、実際の物理的な読み書き回数を減らす2、バッファが作成されるとメモリが割り当てられます.このメモリ領域は常に再利用され、動的なメモリの割り当てと回収回数を減らすことができます.
一般的に実際のプロセスでは、ファイルをメモリに読み込み、メモリから別の場所に書き込むのが一般的です.これにより、入出力中にキャッシュでIO性能を向上させることができます.
Java nioにおいてもバッファの役割は,到来時にデータを格納するものであり,I/O操作におけるデータの中継局と理解できる.バッファは直接チャネル(channel)サービスであり、データをチャネルに書き込むか、チャネルからデータを読み出すことで、バッファデータを利用して伝達すれば、データの効率的な処理の目的を達成することができる.nioには主に8種類のバッファクラス(MappedByteBufferはメモリマッピング専用のByteBuffer):ByteBuffer,CharBuffer,ShortBuffer,IntBuffer,LongBuffer,FloatBuffer,DoubleBuffer

2、Fields


すべてのバッファには、capacity、limit、position、markの4つのプロパティがあり、mark<=position<=limit<=capacityに従います.次の表では、この4つのプロパティの説明を示します.
フィールド
さぎょう
position
現在の読み込み先
limit
現在の書き込み位置
capacity
容量
mark
タグ、mark()を呼び出してmark=positionを設定し、reset()を呼び出すとpositionをタグ位置に復元できます.
私はこのいくつかの方法のテスト方法を書いて、みんなは実行して理解することができます:
public static void main(String[] args) {
        System.out.println("---------test allocate ------------");
        System.out.println("before allocate:"+Runtime.getRuntime().freeMemory());

        // , , jvm ?
        ByteBuffer buffer=ByteBuffer.allocate(102400);
        System.out.println("buffer = "+buffer);
        System.out.println("after allocate:"+Runtime.getRuntime().freeMemory());

        // , jvm 
        ByteBuffer directBuffer=ByteBuffer.allocateDirect(102400);
        System.out.println("directBuffer = "+directBuffer);
        System.out.println("after allocate:"+Runtime.getRuntime().freeMemory());

        System.out.println("----------  test wrap ---------");
        byte[]bytes=new byte[32];
        buffer=ByteBuffer.wrap(bytes);
        System.out.println(buffer);

        buffer=ByteBuffer.wrap(bytes,10,10);
        System.out.println(buffer);
    }

3、その他の一般的な方法


方法
説明
limit(),limit(10)
前者get,後者set
reset()
positionをmarkの値に設定する
clear()
position=0,limit=capacity,mark=-1
flip()
limit=position,position=0,mark=-1;バッファ状態を格納データから取得準備データに変更
rewind()
positionを0、markを-1に設定し、limitの値を変更しない
remaining()
return limit-position
hasRemaining()
return positioncompact
positionからlimitまでの内容を0からlimitまで移動し、positionとlimitの値をそれぞれlimit-position、capacityに変更します.未読のコンテンツもバッファの先頭にコピーされ、bufferはデータを書く準備ができていますが、未読のデータは上書きされません.positionをlimitに設定してcompactするとclearに相当します
get()
相対的に読み、positionからbyteを読み出し、position+1を次回の読み書きに備えます
get(int index)
絶対読み、byteBuffer下層bytesの下にindexと表記されたbyteを読み出し、positionを変更しない
get(byte[]dst,int offset,int length)
positionから相対的に読み、length個byteを読み、dstの下にoffsetからoffset+lengthまでの領域を書き込む
put(byte b)
相対的に書く、positionにbyteを書き、position+1を次回の読み書きに備えます
put(int index,byte b)
絶対書き、byteBufferの下部のbytesにindexと表記された位置にbyte bを挿入し、positionを変更しない
put(ByteBuffer src)
このbyteBufferに対して相対的に書いて、srcで読める部分(position-limit)を書きます.
put(byte[]src,int offset,int length
src配列のoffsetからoffset+lengthへのデータをpositionに書き込み、position+length
以下に、これらのメソッドのテストコードを示します.
 public static void main(String[] args) {
        byte[]bytes=new byte[32];
        ByteBuffer buffer=ByteBuffer.wrap(bytes);
        System.out.println(buffer);

        buffer=ByteBuffer.wrap(bytes,10,10);
        System.out.println("----------Test reset -----------");
        buffer.clear();
        buffer.position(5);
        buffer.mark();
        buffer.position(10);
        System.out.println("before reset:"+buffer);
        buffer.reset();
        System.out.println("after reset:"+buffer);

        System.out.println("----------Test rewind -----------");
        buffer.clear();
        buffer.position(10);
        buffer.limit(15);
        System.out.println("before rewind:"+buffer);
        buffer.rewind();
        System.out.println("after rewind:"+buffer);

        System.out.println("----------Test compact -----------");
        buffer.clear();
        buffer.put("abcd".getBytes());

        System.out.println("before compact:"+buffer);
        System.out.println(new String(buffer.array()));
        buffer.flip();
        System.out.println("after flip:"+buffer);

        System.out.println((char)buffer.get());
        System.out.println((char)buffer.get());
        System.out.println((char)buffer.get());
        System.out.println("after three gets:"+buffer);

        System.out.println("\t"+new String(buffer.array()));
        buffer.compact();
        System.out.println("after compact:"+buffer);

        System.out.println("\t"+new String(buffer.array()));

        System.out.println("----------Test get -----------");
        buffer=ByteBuffer.allocate(32);
        buffer.put((byte)'a').put((byte) 'b').put((byte)'c').put((byte)'d').put((byte)'e').put((byte)'f');
        System.out.println("before flip:"+buffer);
        // 
        buffer.flip();
        System.out.println("before get:"+buffer);
        System.out.println((char)buffer.get());
        System.out.println("after get:"+buffer);

        //get(index) position
        System.out.println((char)buffer.get(2));
        System.out.println("after get(index):"+buffer);

        byte[]dst=new byte[10];
        buffer.get(dst,0,2);
        System.out.println("after get(dst,0,2):"+buffer);
        System.out.println("\t dst:"+new String(dst));
        System.out.println("buffer now is:"+buffer);
        System.out.println("\t"+new String(buffer.array()));

        System.out.println("----------Test put -----------");
        ByteBuffer bb=ByteBuffer.allocate(32);
        System.out.println("before put(byte):"+bb);
        System.out.println("after put(byte):" + bb.put((byte) 'z'));
        System.out.println("after put(2,(byte)'c'):"+ bb.put(2, (byte) 'c'));
        System.out.println("\t"+new String(bb.array()));

        // buffer abcdef[pos=3 limit=6 cap=32]
        bb.put(buffer);
        System.out.println("after put(buffer):"+bb);
        System.out.println("\t"+new String(bb.array()));
    }