Of containers in order in the previous chapter introduced the JDK nio Buffer principle and use: (netty extremely brief tutorial (2) : nio Buffer the principle and use of) [www.jianshu.com/p/9a9feee60]… Next, let’s talk about channels in JDK NIO


Example source: github.com/jsbintask22…

The Channel is introduced

In nio, all channel inherited from * channel (Java. Nio. Channels. The channel) * interface, it represents a connection can be IO operations, can be a hardware device, file, network, etc.


This section uses FileChannel as an example to describe how to use a Channel and implement the interface

  1. WritableChannel writes data from ByteBuffer to a Channelint write(ByteBuffer src)
  2. ReadableChannel reads data from a Channel to ByteBufferint read(ByteBuffer dst)
  3. GatheringByteChannel Multiple ByteBuffers can be written based on WritableChannellong write(ByteBuffer[] srcs)
  4. ScatteringByteChannel Reads data from multiple ByteBuffers based on ReadableChannellong read(ByteBuffer[] dsts)We have described the functions and use of ByteBuffer, but we will focus on the use of FileChannel

FileChannel use

Write data

FileChannel fileChannel = FileChannel.open(Paths.get(""."file_channel_example.txt"),  / / 1
                StandardOpenOption.WRITE,
                StandardOpenOption.READ);

String src = "Hello from jsbintask.cn en 中文\n... test";

// write
ByteBuffer writeBuffer = ByteBuffer.wrap(src.getBytes(StandardCharsets.UTF_8));
fileChannel.write(writeBuffer); / / 2
Copy the code
  1. Get the channel that represents the file connection through the FileChannel open method
  2. Write data from buffer to channel (write to corresponding file)

It is important to note that the override method for obtaining a channel requires that the file already exists. If the file does not exist, the alternative is fileChannel = new FileOutputStream(“file_channel_example.txt”); .getChannel(); Convert via BIO

Read the data

FileInputStream fis = new FileInputStream("file_channel_example.txt");
FileChannel fileChannel = fis.getChannel();  

// read
ByteBuffer readBuffer = ByteBuffer.allocate(100);
int length = fileChannel.read(readBuffer);   / / 1
// method 1
System.out.println(new String(readBuffer.array()));   / / 2

// method 2
readBuffer.flip();
byte[] data = new byte[length];
int index = 0;
while (readBuffer.hasRemaining()) {
    data[index++] = readBuffer.get();
}
System.out.println(new String(data));   / / 3
Copy the code
  1. Read channel data into all buffers
  2. Print the byte data directly from the buffer
  3. Use the position pointer of buffer to get valid data and print it

It is worth noting that the flip method of buffer is called here, because the channel.read() method above has moved the pointer in buffer

copy

With the above write, read already knows the writing method of copy. Here we assume that the allocated buffer is small, so it needs to be copied multiple times

// copy: file_1.txt => file_2.txt
FileChannel fileChannel = new FileInputStream("file_channel_example.txt").getChannel();

// write
FileChannel writeChannel = new FileOutputStream("file_channel_example_copy.txt").getChannel();

// Only a small cache is allocated for multiple reads
ByteBuffer readBuffer = ByteBuffer.allocate(3);  / / 1
int len = -1;
while((len = fileChannel.read(readBuffer)) ! = -1) {  / / 2
    readBuffer.flip();    / / 3
    writeChannel.write(readBuffer);

    readBuffer.clear(); / / 4
}
Copy the code

Zero copy

FileChannel has a way of eliminating the intermediate buffer, which we call zero copy

readChannel.transferTo(0, fis.available(), writeChannel);

writeChannel.transferFrom(readChannel, fis.available(), fis.available());
Copy the code

conclusion

  1. The significance and function of channel
  2. Writable, readable, Gatherting, Scattering methods added to the interface
  3. Use of FileChannel and zero copy