Channel classification in Java NIO:
- FileChannel
- SocketChannel
- ServerSocketChannel
- DatagramChannel
FileChannel: Used to read and write files from or to a disk.
SocketChannel: Reads data from or writes data to the Channel of the TCP connection used for the Socket
ServerSocketChannel: The ServerSocketChannel listens for TCP connections. After the server listens for connections, it creates a SocketChannel for each request
DatagramChannel: used for reading and writing UDP data
Next, we will introduce them respectively.
FileChannel
Mainly used for operating documents, nonsense not to say, see examples directly.
TXT file, containing shDEQuanZhanBiJi
Input a FileInputStream
The FileChannel input stream is used to read data from the FileChannel, for example, by entering a specified file into the FileChannel to retrieve the file’s contents.
public static void main(String[] args) throws IOException {
// Create an input stream
FileInputStream fileInputStream = new FileInputStream("test-file.txt");
// Get the channel from the input stream
FileChannel fileChannel = fileInputStream.getChannel();
// Prepare ByteBuffer
ByteBuffer buffer = ByteBuffer.allocate(16);
// Read the channel data of the input stream into buffer
fileChannel.read(buffer);
// Simply print the contents of the buffer
printBuffer(buffer); // shDEQuanZhanBiJi
}
Copy the code
The ByteBuffer is the medium through which a channel reads and writes data. To read data from a channel (as in the above example), the data needs to be read into a ByteBuffer; In the same way, to write data to a channel, you need to write data to a ByteBuffer (we’ll talk about output streams below).
If you are not familiar with ByteBuffer, you can take a look at the code for printBuffer
Output FileOutputStream
As the name implies, a FileChannel outputs data, such as writing data to a disk file. Here’s an example:
public static void main(String[] args) throws IOException {
// Specify the name of the file to be generated
String generateFileName = "generate-file.txt";
// Create an output stream
FileOutputStream fileOutputStream = new FileOutputStream(generateFileName);
// Get the channel from the output stream
FileChannel fileChannel = fileOutputStream.getChannel();
// Prepare ByteBuffer and write data to it
ByteBuffer buffer = ByteBuffer.allocate(16);
buffer.put("shDEQuanZhanBiJi".getBytes(StandardCharsets.UTF_8));
// Read the channel data of the input stream into buffer
fileChannel.write(buffer);
fileChannel.close();
}
Copy the code
The corresponding comments have been posted on the corresponding code, and the details will not be covered here. The only thing of concern is that the call to write the file to disk is also the ByteBuffer passed in first.
Well, when you’re done running the code you’ll find that even though the file was generated, it’s empty… This actually involves the familiarity of ByteBuffer, which is a pit to bury.
If you don’t know why the file is empty, check out the ByteBuffer article above.
This is because ByteBuffer is created in write mode by default and cannot be read by position and limit. So before calling write, we need to switch ByteBuffer to read mode first. The complete code is as follows:
public static void main(String[] args) throws IOException {
// Specify the name of the file to be generated
String generateFileName = "generate-file.txt";
// Create an output stream
FileOutputStream fileOutputStream = new FileOutputStream(generateFileName);
// Get the channel from the output stream
FileChannel fileChannel = fileOutputStream.getChannel();
// Prepare ByteBuffer and write data to it
ByteBuffer buffer = ByteBuffer.allocate(16);
buffer.put("shDEQuanZhanBiJi".getBytes(StandardCharsets.UTF_8));
// Set ByteBuffer to read mode
buffer.flip();
// Read the channel data of the input stream into buffer
fileChannel.write(buffer);
fileChannel.close();
}
Copy the code
As you can see, the file is generated and the content is available:
However, the above two can only be written or read. FileInputStream, for example if you stubbornly Dui data into the channel and program finally throws NonWritableChannelException abnormalities, can’t tell you this thing to write.
Is there an implementation that can write, read and sing? Of course there is. That’s RandomAccessFile.
For the record, the write call is not immediately written to disk, but can also be stored in the operating system cache. If the disk needs to be flushed immediately, call channel.force(true); Can.
RandomAccessFile
How does it work? It’s pretty much the same as the other two:
public static void main(String[] args) throws IOException {
// Specify the name of the file to be generated
String targetFileName = "target-file.txt";
// Create RandomAccessFile with read (r) and write (w) permissions
RandomAccessFile accessFile = new RandomAccessFile(targetFileName, "rw");
FileChannel fileChannel = accessFile.getChannel();
// Create ByteBuffer and write data
ByteBuffer buffer = ByteBuffer.allocate(16);
buffer.put("shDEQuanZhanBiJi".getBytes(StandardCharsets.UTF_8));
// Switch to read mode of buffer
buffer.flip();
// Call write to write buffer data to channel, channel writes data to disk file
fileChannel.write(buffer);
// Empty the buffer
buffer.clear();
// Read the data previously written to channel into buffer
fileChannel.read(buffer);
// Prints the contents of buffer
printBuffer(buffer);
fileChannel.close();
}
Copy the code
As a result, a file named target-file. TXT is generated with the name shDEQuanZhanBiJi. And the console will print out the shDEQuanZhanBiJi that was previously written to the channel.
As always, the details are in the notes. Note that new RandomAccessFile(targetFileName, “rw”); In the rw. It is also stated in the comment, which stands for granting readable and writable permissions.
It’s also worth noting that you can’t say change rw to w.
You can’t play it that way, because it’s a pure string match, and there’s only so much you can do:
As you can see, r is essential… :
r
Can only readrw
Both canread, also canwriterws
和rwd
Function andrw
It’s basically the same, readable, writable. The only difference is that they force every change to disk, andrws
The operating system will also brush the metadata of the file, which reflects that the update time of the file will be updated, andrwd
The metadata of the file will not be flushed
Two SocketChannel
Since these two are responsible for connection transmission, the other is responsible for connection monitoring, so put together. Here’s what we’re going to do in this section:
But in order for you to run it directly, instead of reading from disk files on the client side, you use ByteBuffer. You can run it and try to load it from disk yourself. Let’s start with the server code:
ServerSocketChannel
public static void main(String[] args) throws IOException {
// Open a ServerSocketChannel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// Bind port 8080
serverSocketChannel.bind(new InetSocketAddress(8080));
// Start accepting client connections
SocketChannel socketChannel = serverSocketChannel.accept();
// The connection is successfully obtained
System.out.printf("socketChannel %s connected\n", socketChannel);
// Prepare ByteBuffer to read data from socketChannel
ByteBuffer buffer = ByteBuffer.allocate(16);
// Start reading data
System.out.println("before read");
int read = socketChannel.read(buffer);
System.out.printf("read complete, read bytes length: %s \n", read);
printBuffer(buffer);
}
Copy the code
Here we are using the default blocking mode in Java NIO, just as a cover. If you want ServerSocketChannel to enter non-blocking mode, you can call it after opening:
serverSocketChannel.configureBlocking(false);
Copy the code
Because we are here in a blocking mode, so in the code to run to serverSocketChannel. The accept (); Is blocked until a client comes to establish a connection. Similarly, the read method blocks, and if the client never writes data, the server will always block on read.
SocketChannel
Give the code directly first:
public static void main(String[] args) throws IOException {
// Open a SocketChannel
SocketChannel socketChannel = SocketChannel.open();
// Connect to port 8080 of localhost
socketChannel.connect(new InetSocketAddress("localhost".8080));
/ / for ByteBuffer
ByteBuffer buffer = ByteBuffer.allocate(16);
buffer.put(Charset.defaultCharset().encode("test"));
// Switch buffer to read mode & write data to channel
buffer.flip();
socketChannel.write(buffer);
}
Copy the code
Start the server and then the client. You can see that the console on the server side has the following output:
[connected socketChannel Java nio. Channels. A socketChannel local = / 127.0.0.1: remote = 8080/127.0.0.1:64373] connected before read read complete, read bytes length: 4 BUFFER VALUE: testCopy the code
Datagram
This one is a bit simpler, starting with the client code:
public static void main(String[] args) throws IOException {
DatagramChannel datagramChannel = DatagramChannel.open();
// Build buffer data
ByteBuffer buffer = ByteBuffer.allocate(16);
buffer.put(Charset.defaultCharset().encode("test"));
// Switch to read mode of buffer
buffer.flip();
datagramChannel.send(buffer, new InetSocketAddress("localhost".8080));
}
Copy the code
Then there is the server:
public static void main(String[] args) throws IOException {
DatagramChannel datagramChannel = DatagramChannel.open();
datagramChannel.bind(new InetSocketAddress(8080));
ByteBuffer buffer = ByteBuffer.allocate(16);
datagramChannel.receive(buffer);
printBuffer(buffer);
}
Copy the code
Welcome to wechat search and follow [SH full stack Notes]. If you think this article is helpful to you, please click a like, close a note, share a share and leave a message.