This article has participated in the weekend study program, click the link to see details: juejin.cn/post/696572…

What is an IO stream

JavaIO stream is a computer term. It is mainly used to process the transmission of data. — Baidu Encyclopedia

A stream is a flow of data, and an IO stream is a flow of input and output. In Java, data is streamed. Data cannot be transferred from one device to another at once, so it can only be streamed bit by bit. An input stream reads data from somewhere else into the program, and an output stream writes data from the program to somewhere else.

Two, IO stream classification

1. Four abstract classes

IO provides four of the most important abstract classes: InputStream,OutputStream,Reader, and Writer.

A character is equal to two bytes. According to the units of data output, there are two types, byte streams and character streams

Graph LR ((byte stream)) - enter A - > B (InputStream) A output -- -- -- > C (OutputStream) D (flow) (characters) - input - output - > E (Reader) D - > F (Writer)

You can also divide it into input streams and output streams depending on the input or output and depending on what you’re doing, you can also divide it into node streams and processing streams and a node stream is reading or writing data from a particular node. When you look at a node, it feels esoteric. Basically, it means reading or writing data from a place, which can be a database, a console, a file, etc. The processing flow is the proxy node flow that implements some other function. For example, a BufferedWriter can only write one character at a time if it is a normal FileWriter. If a BufferedWriter is installed, it can write more quickly.

2. Various implementation classes

Graph LR A((InputStream))-->AN[node stream] AN-->A1(FileOutputStream) AN-->A2(PipedOutputStream) AN-->A3(ByteArrayOutputStream) A5(PrintStream) AH-->A6(DataOutputStream) AH-->A7(ObjectOutputStream) AH-->A7(ObjectOutputStream) B((OutputStream))-->BN[node stream] BN-->B1(FileInputStream) BN-->B2(PipedInputStream) BN-->B3(ByteArrayInputStream) B-->BH  BH-->B4(BufferedInputStream) BH-->B5(SequenceInputStream) BH-->B6(DataInputStream) BH-->B7(ObjectInputStream) BH-->B8(PrintStream) D((Reader))-->DN DN-->D1(FileReader) DN-->D2(PipedReader) DN-->D3(CharArrayReader) D-->DH DH-->D4(BufferedReader) DH-->D5(InputStreamReader) C((Writer))-->CN (node stream) CN-->C1(FileWriter) CN-->C2(PipedWriter) C--> C5(InputStreamWriter) C--> C6(PrintWriter) C--> C5(InputStreamWriter) C--> C6(PrintWriter)

There may be some omissions, more detailed can see the Java official documentation.

How to use it

Take FileInputStream and FileOutputStream for example

Code 1.

package test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

/ * * *@authorXXJ * IO stream test */
public class IOTest {
    public static void main(String[] args) {
       // Open a file first
        File file= new File("C:\\Users\\Administrator\\Desktop\\test.txt");
        try{
            // Write data first
            FileOutputStream fileOutputStream=new FileOutputStream(file);
            fileOutputStream.write("ABCD".getBytes());
            fileOutputStream.close();
            // Read the data
            FileInputStream fileInputStream=new FileInputStream(file);
            int i= 0;
            while((i=fileInputStream.read())! = -1){
                System.out.println("Data read via a fileInputStream:"+i);
                System.out.println("Data read via a fileInputStream:"+ (char)i);
                System.out.println("-- -- -- -- -- -");
            }
            fileInputStream.close();
        }catch (Exception e){}
    }
}
Copy the code

2. Output the result

Because I added (char) I automatically converted the ASCII code table and my desktop also generated test.txt, so take the code and run with it.

3. Explain

You might say, well, you’re not doing this right, you’re not doing a FileInputStream and you’re not doing a FileOutputStream, why is it that each read happens to be one letter, not one byte? A byte is eight bits. If you look at the ASCII code table, there are already hundreds of symbols or letters in it. You can’t just use four bits to represent them, but at least eight bits.

Take FileReader and FileWriter for example

Code 4.

public class IOTest {
    public static void main(String[] args) {
        try{
            / / write first
            File file=new File("C:\\Users\\Administrator\\Desktop\\writer.txt");
            FileWriter fileWriter=new FileWriter(file);
            fileWriter.write("ABC one two three");
            fileWriter.close();
            / / read
            FileReader fileReader=new FileReader(file);
            int i=0;
            while((i=fileReader.read())! = -1){
                System.out.println("Data read by reader:"+i);
                System.out.println("Data read by reader:"+ (char)i);
                System.out.println("-- -- -- -- -- -");
            }
            fileReader.close();
        }catch (Exception e){}
    }
}
Copy the code

5. Output the result

6. Explain

I have a question, why FileReader can read letters, just like FileInputStream, then why can it read just one Chinese and one letter? 19968=0x4e00 writer.txt is

4142 43 e4b8 80e4 ba8c e4b8 89
Copy the code

There’s no 4e00, Then we convert it to binary (1) 19968=100111000000000 (2) 20108=100111010001100 (3) 19977=100111000001001 0 xe4b880e4ba8ce4b889 = 111001001011100010000000111001001011101010001100111001001011100010001001 I used String. The replace () method, E4b8 80E4 ba8c E4b8 89 does not contain the binary of one, two and three.

This is where encodings come in. The common list of encodings that support Chinese is UTF-8, so I pulled 1, 2, 3 into it to see the base conversion

This. It’s really a set of things. At this point, it’s not clear exactly how do you decide to read only one byte or read only one character

Four, the characteristics of various IO streams

Different IO stream use is similar, but there are some different details, specific can look up Baidu or directly see the source code of each implementation class, After all, they all inherit InputStream,OutputStream,Reader, and Writer, respectively, and the processing stream is indirectly inherited from the Filter stream.

The last write to the FileOutputStream is with the native modifier.

private native void writeBytes(byte b[], int off, int len, boolean append)
        throws IOException;
Copy the code

The difference between byte streams and character streams

  1. Byte streams can operate only one byte at a time, and character streams can operate two bytes
  2. Byte streams can handle any file type, while character streams can only handle text files

1. The node flow

The File stream

Bytes: FileInputStream, FileOutputStream Characters: FileReader, FileWriter

The characteristics of

All of these require the creation of a File object before they can be used, and all read and write operations are done on the created File object. The only difference is that the first two are byte streams and the last two are character streams, which are used if you want to read or write Chinese.

Piped flow

Byte: PipedInputStream, PipedOutStream, character: PipedReader, PipedWriter generally is used for communication between threads

The characteristics of

When using these streams, you don’t need to create a File object as compared to a File stream, you just create it like a normal stream, but before the Piped can communicate with each other, you need to connect the two pipes using the connect method

A Piped stream does not need to use a file as a carrier of data.

Byte/character array stream

Bytes: ByteArrayInputStream, ByteArrayOutputStream Characters: CharArrayReader, CharArrayWriter

Each of these four streams has an array inside it, and is used to store data into the array, read from the array, or write the data from the array elsewhere.

The characteristics of

Byte: only bytes can be read or written. ByteArrayInputStream is created by passing a parameter (an array of bytes) to the constructor and ByteArrayOutputStream is used by calling writeTo. These two streams help us to store data in the cache first and then read and write more quickly. CharArrayWriter is similar to ByteArrayInputStream or ByteArrayOutputStream, except that Char starts with read and write characters. Byte is reading and writing bytes, which is the same thing.

2. The processing flow

When processing streams are used, they need to be nested with a node stream, and then use the same method as using node streams.

Buffered stream buffer

Byte: BufferedInputStream, BufferedOutputStream characters: BufferedReader, BufferedWriter

These four streams are similar to byte/character streams in that they also have an internal array that acts as a cache. However, the byte/character array stream caches data into the array. It does not flush the array. It reads or writes from the array. Buffered has an array that does not change twice (you can pass size in the constructor). Once the array is full, the array is read or written to somewhere else, and then the array is flushed.

Byte/character array streams are recommended to be closed once used.

The characteristics of

After using other node streams, the method is similar to that used for node streams, but a flush() method is used to flush all the data inside the cache when the Buffered stream is written.

Transformation of flow

Characters: InputStreamReader, OutputStreamWriter

The characteristics of

The ability to convert a byte stream into a character stream is created by passing a byte stream and character set (GBK by default) to the constructor in much the same way as a character stream.

The data flow

Bytes: DataInputStream, DataOutputStream

The characteristics of

Data flow is the ability to write data according to different types and read data according to the corresponding type. Just like when you write, you put data into boxes of different types. When you read, you read according to the box type and in the order in which it was written.

Printing flow

Byte: PrintStream Character: PrintWriter

The characteristics of

These two streams do not have corresponding input streams and are used in the same way as any other processing stream. Once a node stream is mounted, the data can be written directly using print() or println(). System.out.println() is a method that uses PrintStream internally.

Object flow

Bytes: ObjectInputStream, ObjectOutputStream

The characteristics of

One thing these two streams can do is serialize the data we are writing to or reading from. Serialization is the conversion of objects to binary data. To use these two streams, the first step is to install a node stream, the second step is to implement the Serializable interface on the class to be serialized, and the rest of the usage is similar to a normal node stream.

Five, the summary

These streams are really a lot, so let’s summarize the usage scenarios. Both write and read are text types and Chinese, we use character streams. To write or read any other miscellaneous file type without Chinese, use a byte stream. To consider threaded communication, use Piped streams; To manipulate a File, use the File stream; To store data in memory, use byte/character array streams, no performance or functionality requirements, these three are sufficient. To improve read/write performance, use a Buffered stream. If you want a data format, create a data stream. For ease of use or line feed, use a print stream; To serialize an object, create an object stream.

— — — — — — — — — — — — — — —

The more you know, the more you don’t know.

If you have questions about this article, please comment directly or send me a personal message. If you think my writing is good, you can also support me by clicking “like”

Without permission, shall not be reproduced!

Wechat search [programmer Xu Xiaobai], attention can be the first time to read the latest articles. There are 50 high frequency college recruitment interview questions prepared by me, as well as a variety of learning materials.