Analysis of common methods of ByteBuffer

Cited examples

Take an example to illustrate the differences of these methods in ByteBuffer in combination with graphics

public class ByteBufferDemo {
    public static void main(String[] args) {
        ByteBuffer buffer = ByteBuffer.allocate(10);
        //8 bytes are required to store Double here. If the ByteBuffer space is less than 8 bytes, an error bufferoverflow exception will be reported
        byte[] bytes=new byte[]{'a','b','c'};
        buffer.put(bytes);
				//Flip byteBuffer from write mode to read mode
        buffer.flip();
        while(buffer.hasRemaining()){
   			 System.out.println(buffer.get());
				}
    }

Output results

97
98
99

In the above case, a bytebuffer with a capacity of 10 is initialized

position=0, limit=capacity=10. In write mode, position is the write position, and limit is equal to capacity

After inserting a byte array

flip method

The default implementation of ByteBuffer is HeapByteBuffer

public final Buffer flip() {
        limit = position;
        position = 0;
        //Clear mark
        mark = -1;
        return this;
    }

After calling the flip method,

After switching to the read mode, the data will be read from position - > limit. After reading

Mark & & reset method

These two methods are mainly used to mark position and reset position to the marked position

public final Buffer mark() {
        mark = position;
        return this;
    }

public final Buffer reset() {
        int m = mark;
        if (m < 0)
            throw new InvalidMarkException();
        position = m;
        return this;
    }

For example, if there is a need to re read the data from a position

public class ByteBufferDemo3 {
    public static void main(String[] args) {
        ByteBuffer buffer = ByteBuffer.allocate(10);
        byte[] bytes=new byte[]{'a','b','c'};
        buffer.put(bytes);
        //Flip byteBuffer from write mode to read mode
        buffer.flip();
        System.out.println(buffer.get());
        //sign
        int position = buffer.position();
        System.out.println("stay position="+position+"Mark at");
        buffer.mark();

        while(buffer.hasRemaining()){
            System.out.println(buffer.get());
        }

        buffer.reset();

        System.out.println("Again from position="+position+"Read data at");

        while(buffer.hasRemaining()){
            System.out.println(buffer.get());
        }

    }
}

Output:

97
Mark position=1
98
99
Read the data from position=1 again
98
99

At first, after inserting the byte array, the buffer is as follows

After calling the flip and get() methods, the buffer is as follows

Buffer Mark() marks position=1

After the first traversal of the buffer from position=1

Call buffer Buffer after reset()

Therefore, you can read the data from position=1 again

clear method

public class ByteBufferDemo {
    public static void main(String[] args) {
        ByteBuffer buffer = ByteBuffer.allocate(10);
        byte[] bytes=new byte[]{'a','b','c'};
        buffer.put(bytes);
        //Flip byteBuffer from write mode to read mode
        buffer.clear();
        while(buffer.hasRemaining()){
            System.out.println(buffer.get());
        }
    }
}

Output result:

97
98
99
0
0
0
0
0
0
0

Through observation, it is found that the clear method can also flip the buffer. What is the difference between it and flip?

public final Buffer clear() {
        position = 0;
        limit = capacity;
        //Clear mark
        mark = -1;
        return this;
    }

It can be found that it sets the pointers in the buffer to the initial value.

At this time, if you read limit from position, you will read a lot of empty data. After reading, the buffer pointer is as follows

Therefore, if you want to use the clear method, try to ensure that the buffer data is full, otherwise useless data will be read out. Example

public class ByteBufferDemo2 {
    public static void main(String[] args) {
        byte[] bytes=new byte[]{'a','b','c'};
        ByteBuffer buffer = ByteBuffer.wrap(bytes);
        buffer.put(bytes);
        //Flip byteBuffer from write mode to read mode
        buffer.clear();

        while(buffer.hasRemaining()){
            System.out.println(buffer.get());
        }
    }
}

Output result:

97
98
99

If you insert data again after the clear method, you need to pay attention, because the position position may change, resulting in incomplete read data.

public class ByteBufferDemo2 {
    public static void main(String[] args) {
        ByteBuffer buffer = ByteBuffer.allocate(10);
        byte[] bytes=new byte[]{'a','b','c'};
        buffer.put(bytes);
        //Flip byteBuffer from write mode to read mode
        buffer.clear();
        buffer.put((byte) 100);
      //buffer.flip();
        while(buffer.hasRemaining()){
            System.out.println(buffer.get());
        }
    }
}

Output result:

98
99
0
0
0
0
0
0
0

The put method is called after the clear() method.

Because the put method moves position, the data just inserted cannot be read. If you don't want to move the position, you can try to specify the index when putting, so that the position won't be moved

Note: if the above buffer put((byte) 100); After calling the flip method, position=0 and limit=1 can only read characters inserted just now.

Therefore, when using the clear method, we should weigh how to get the data and how to get the data.

compact method

This method is different from the previous one. It compresses the unread part forward and then switches to write mode

public ByteBuffer compact() {
				//Copy data copy data from position, receive data from hbindex=0, copy length = limit position
        System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
        //Reset buffer position
        position(remaining());
        //Reset limit limit
        limit(capacity());
        //Clear mark mark
        discardMark();
        return this;
    }

Examples

public class ByteBufferDemo {
    public static void main(String[] args) {
        ByteBuffer buffer = ByteBuffer.allocate(10);
        byte[] bytes=new byte[]{'a','b','c'};
        buffer.put(bytes);
        //Flip byteBuffer from write mode to read mode
        buffer.flip();
        buffer.get();

        buffer.compact();

        buffer.put((byte) 'd');
        buffer.put((byte) 'e');

        buffer.flip();

        while(buffer.hasRemaining()){
            System.out.println(buffer.get());
        }


    }
}

Output result:

98
99
100
101

After calling the flip and get methods, the buffer is as follows

After the compact() method is called, the buffer is as follows

Because buffer was called earlier Get() so the original position=1 and the original limit=3

position=limit - original position=3-1=2, limit=capacity=10

After calling the put method twice again

The later read data will not be repeated.

summary

Don't forget to call the flip method when switching between read and write

Added by yoma31 on Mon, 07 Feb 2022 07:15:40 +0200