Recently, I plan to deepen my knowledge of Java network programming (IO, NIO, Socket programming, Netty).
Java I/O streams
Java Network Programming
Java NIO: Buffers
Java NIO: Channels
Java NIO: selector
Java I/O is built on streams. The input stream reads data and the output stream writes data
Input-output stream
The input stream
The API for InputStream is as follows:
public abstract int read(a) throws IOException;/ / - 1 to 255
public int read(byte b[]) throws IOException
public int read(byte b[], int off, int len) throws IOException
public long skip(long n) throws IOException
public int available(a) throws IOException
public void close(a) throws IOException
Copy the code
The read() method actually returns an unsigned byte(Java doesn’t have an unsigned byte, so int is returned).
The read method returns -1 to indicate that the data has been read (or, in the case of network communication, that the peer end will not send any more data)
The output stream
The output stream OutputStreamAPI is as follows:
// The OutputStream interface defines several methods
public abstract void write(int b) throws IOException;
public void write(byte b[]) throws IOException
public void write(byte b[], int off, int len) throws IOException
public void flush(a) throws IOException
public void close(a) throws IOException
Copy the code
The write(int) method actually writes the lower 8 bits (one byte) of int.
Try not to use write(int), because sending one byte at a time is inefficient (each TCP packet has at least 40 bytes of network transmission overhead, and the channel utilization rate is not high if the data is too small).
Flush () flushes the contents of the buffer to the underlying output stream
Close the stream
The stream corresponds to the underlying file handle and port, so be sure to close it when you’re done using it
The following is a common way to close a stream (ina finally statement block), but it’s too complicated!!
FileInputStream in = null;
try {
in = new FileInputStream("/tmp/axt.t");
//
} catch (FileNotFoundException e) {
//
} finally {
if(in ! =null) {try {
in.close();
} catch (IOException e) {
//}}}Copy the code
Let me write it a little bit neater
try(FileInputStream in = new FileInputStream("/tmp/a.txt")) {// do somethind
} catch (Exception e) {
//
}
Copy the code
Because Java automatically calls the close() method on all objects of type AutoCloseable declared in the try block, there is no need to call it manually!
The filter flow
The filter flow is actually an enhancement of the flow function, using decorator mode.
Decorative pattern
Decoration mode is to add some new functions on the basis of the original, through combination.
Below is the filter flow class structure – the embodiment of the decorator pattern
The role of filter flow
The following code wraps FileInputStream with BufferedInputStream and DataInputStream
Allows the user to read characters directly from the Java buffer (if no data is available in the buffer, try reading from the underlying input stream)
FileInputStream in = new FileOutputStream("/tmp/a.txt");
in = new BufferedInputStream(in);
in = new DataInputStream(in);
in.readChar();
Copy the code
Filter streams can also be decompressed (ZIPInputStream), Base64InputStream decoded (Base64InputStream), and can also be customized for specific functions.
Buffer flow
Buffer flow is a kind of filter flow. In network communication scenarios, buffering improves the efficiency of sending and receiving data.
We should use BufferedOutputStream when sending data, so that the data is written to the Java buffer first, and the data is not sent until the buffer is full or the flush method is called.
OutputStream out = new FileOutputStream("/tmp/a.txt");
BufferedOutputStream outputStream = new BufferedOutputStream(out);
out.write(1);
out.flush();
Copy the code
The data flow
Buffered flows, as one of the filter flows, provide apis for reading and writing Java primitive types directly
OutputStream out = new FileOutputStream("/tmp/a.txt");
DataOutputStream dataOutputStream = new DataOutputStream(out);
dataOutputStream.writeChar('c'); / / write characters
dataOutputStream.writeUTF("ssss"); // Write a string
Copy the code
Readers and writers
Provides an API for reading and writing characters (if only ASCII encoding, use byte stream directly)
writer
OutputStreamWriter provides the ability to read characters and strings directly
OutputStream out = new FileOutputStream("/tmp/a.txt"); // The bottom byte stream
Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);
writer.write("Ha ha ha.");
Copy the code
Buffer writer
BufferedWriter Provides a layer of write buffering (a BufferedOutputStream that acts like a byte stream)
Demo
OutputStream out = new FileOutputStream("/tmp/a.txt"); // The bottom byte stream
Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);// write (encoding)
writer = new BufferedWriter(writer, 1000);// Buffer writer
for (int i = 0; i < 128; i ++){
writer.write(i);
}
writer.write("Ha ha ha ha ha.");// Write Chinese characters, utF-8 encoding visible, ASCII encoding will be garbled
writer.flush(); // We don't need to flush, we should flush before close.
writer.close(); // Close the flow to release the underlying resources.
Copy the code
conclusion
The total is divided into two types of byte stream and character stream. Character stream is just a decoration of byte stream (or the bottom layer of character stream is byte stream).
Filter stream: Add some additional features to the base stream such as buffering, compression, encryption, etc
Buffer flow: A buffer layer is added between read and write data to improve data transmission efficiency.