Buffers in Java NIO are used to interact with NIO channels. Data is read from the channel into the buffer and written from the buffer to the channel.

Buffers are essentially blocks of memory from which data can be written and then read. This chunk of memory is wrapped as a NIO Buffer object and provides a set of methods for easy access to the chunk of memory.

1 Basic Usage

Using Buffer to read and write data generally follows the following four steps:

  1. Write data to Buffer
  2. callbuffer.flip()
  3. Read data from Buffer
  4. Call clear() or Compact ()

When writing data to buffer, buffer keeps track of how much data was written. Once the data is read, flip() is used to cut Buffer from write mode to read mode. In read mode, all data previously written to buffer can be read.

Once the data is read, the buffer needs to be emptied so that it can be written again. There are two ways to clear the buffer: call the clear() or compact() methods. The clear() method clears the entire buffer. The compact() method only clears data that has already been read. Any unread data is moved to the beginning of the buffer, and newly written data is placed after the unread data in the buffer.

Examples of using Buffer:

RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt"."rw");
FileChannel inChannel = aFile.getChannel();

//create buffer with capacity of 48 bytes
ByteBuffer buf = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buf); //read into buffer.
while(bytesRead ! = -1) {

  buf.flip();  //make buffer ready for read

  while(buf.hasRemaining()){
      System.out.print((char) buf.get()); // read 1 byte at a time
  }

  buf.clear(); //make buffer ready for writing
  bytesRead = inChannel.read(buf);
}
aFile.close();
Copy the code

Capacity,position, and limit of a Buffer

capacity

As a block of memory, a Buffer has a fixed size, called capacity. You can only write capacity bytes, long, char, etc. Once the Buffer is full, it needs to be emptied (by reading or erasing data) before more data can be written into it.

position

Depending on whether the Buffer is in read or write mode:

  • When writing data to Buffer, position represents the current position. The initial position value is 0. When a byte or long is written to the Buffer, position is moved forward to the next Buffer cell that can insert data. Therefore, the maximum value of position is capacity – 1.
  • When data is read, it is also read from a specific location. Position is reset to 0 when Buffer is switched from write mode to read mode. When data is read from position in the Buffer, position moves forward to the next readable position.

limit

  • In write mode, it indicates the maximum amount of data that can be written to Buffer. So at this timelimit=capacity.
  • In read mode, limit indicates the maximum amount of data that can be read.

Therefore, when Buffer is switched to read mode, limit is set to position in write mode. That is, you can read all the data previously written (limit is set to the number of written data, which in write mode is position).

The type of the Buffer

  • Java NIO buffers have the following types

These Buffer types represent different data types by which bytes in the Buffer can be manipulated.

The distribution of the Buffer

To get a Buffer object, you first allocate it. Each Buffer class has an allocate method.

An example of a ByteBuffer that allocates 48 bytes of capacity.

ByteBuffer buf = ByteBuffer.allocate(48);
Copy the code

Allocate a CharBuffer that can store 1024 characters:

CharBuffer buf = CharBuffer.allocate(1024);
Copy the code

Write data to Buffer

There are two ways to write data to Buffer:

  1. Write from Channel to Buffer
int bytesRead = inChannel.read(buf); //read into buffer.
Copy the code
  1. Write to Buffer via the put() method of Buffer.
buf.put(127);
Copy the code

There are many versions of the PUT method that allow you to write data to buffers in different ways. For example, write to a specified location, or write an array of bytes to a Buffer.

Flip () method

The flip method switches Buffer from write mode to read mode. Calling the flip() method sets position back to 0 and limit to the value of the previous position.

In other words, position is now used to mark the read position, and limit indicates how many bytes, char, etc., were previously written in — how many bytes, char, etc., can now be read.

Read data from Buffer

Two ways:

  1. Read data from Buffer to Channel.
int bytesWritten = inChannel.write(buf);
Copy the code
  1. Read data from Buffer using the get() method.
byte aByte = buf.get();
Copy the code

There are many versions of the GET method that allow you to read data from Buffer in different ways. For example, reading from a specified position, or reading from a Buffer into a byte array.

rewind()

Buffer.rewind() sets position to 0, so all data in Buffer can be re-read. Limit remains the same and still indicates how many elements can be read from Buffer.

Clear () and Compact () methods

Once the Buffer has been read, it needs to be ready to be written again. This is done through clear() or Compact ().

  • Call the clear ()

Position will be set to 0 and limit to the value of capacity. That is, the Buffer is cleared. The Buffer is not cleared, but the flags tell us where to start writing to the Buffer. If there is some unread data in the Buffer, call clear() and the data will be “forgotten,” meaning there will no longer be any markers telling you which data has been read and which has not. If there is still unread data in Buffer and you want to read it later, but you need to write some data first, use Compact ().

  • compact()

Copy all unread data to the start of Buffer. Position is then set directly after the last unread element. The limit property is set to Capacity as in the clear() method. Buffer is now ready to write data, but does not overwrite unread data.

Mark () and reset() methods

A specific position in a Buffer can be marked by calling the buffer.mark () method. This position can then be restored by calling buffer.reset (). Such as:

buffer.mark();
// call buffer.get() a couple of times, e.g. during parsing.
buffer.reset(); 
Copy the code

Equals () and compareTo() methods

Two buffers can be compared using the equals() and compareTo() methods.

equals()

Two buffers are equal if the following conditions are met:

  1. Have the same type (byte, char, int, etc.)
  2. The number of bytes, chars, and so on remaining in the Buffer is equal
  3. All remaining bytes, chars, and so on in the Buffer are identical.

Equals is only part of the Buffer to compare, not every element in it. In fact, it only compares the remaining elements in the Buffer.

compareTo()

The compareTo() method compares the remaining elements (byte, char, etc.) of two buffers and considers one Buffer to be “smaller” than the other if the following conditions are met:

  1. The first unequal element is smaller than the corresponding element in the other Buffer
  2. All elements are equal, but the first Buffer runs out before the other (the first Buffer has fewer elements than the other Buffer).

The remaining elements are from position to limit.

reference

  • Tutorials.jenkov.com/java-nio/bu…