Explain IO flow knowledge in simple terms - advanced flow

Posted by Santonian on Tue, 08 Mar 2022 09:04:53 +0100

There are thousands of people in the vast sea. Thank you for seeing here this second. I hope my article is helpful to you!

May you keep your love and go to the mountains and seas in the future!

πŸ˜‹ I/O advanced flow

😎 1. Buffer flow

Buffered streams, also known as efficient streams, are enhancements to output and input streams.

🐏 1.1 classification of buffer streams

πŸ‘ 1.2 basic principle of buffer flow

When creating a stream object, a built-in buffer array of default size will be created to reduce the number of system IO through buffer reading and writing, so as to improve the efficiency of reading and writing.

🐐 1.3 byte buffer stream

πŸͺ 1.3.1 construction method

  • public BufferedInputStream(InputStream in): to create a new buffered input stream, you need to pass in an InputStream type parameter.
  • public BufferedOutputStream(OutputStream out): to create a new buffered output stream, you need to pass in an OutputStream type parameter.

    The demonstration is as follows:

    public class BufferedTest {
        public static void main(String[] args) throws FileNotFoundException {
            //Construction method 1: create byte buffered input stream [but the following format declaration is commonly used in development]
            FileInputStream fps = new FileInputStream("e:\\demo\\b.txt");
            BufferedInputStream bis = new BufferedInputStream(fps);
    
            //Construction method 1: create byte buffered input stream
            BufferedInputStream bis2 = new BufferedInputStream(new FileInputStream("e:\\demo\\b.txt"));
    
            //Construction mode 2: create byte buffered output stream
            FileOutputStream fos = new FileOutputStream("e:\\demo\\b.txt");
            BufferedOutputStream bos = new BufferedOutputStream(fos);
        
            //Construction mode 2: create byte buffered output stream
            BufferedOutputStream bos2 = new BufferedOutputStream(new FileOutputStream("e:\\demo\\b.txt"));
        }
    }
    

🐫 1.3.2 feel efficient

Since the buffer flow is called efficient flow, we have to test it. It's a mule or a horse that pulls it out.

Let's feel it first:

public class BufferedTest2 {
    public static void main(String[] args) {
        //Use multithreading to test the replication speed of both at the same time.
        new Thread(() -> oldCopy()).start();//This is the Lambda expression in the new feature of JDK8
        new Thread(() -> bufferedCopy()).start();
        
        /*
           As is equivalent to:
           new Thread(new Runnable() {
                @Override
                public void run() {
                    oldCopy();
                }
            }).start();
         */
    }

    public static void oldCopy() {
        // Record start time
        long start = System.currentTimeMillis();
        // Create flow object
        try (
                FileInputStream fis = new FileInputStream("e:\\demo\\Kobe speech.mp4");
                FileOutputStream fos = new FileOutputStream("e:\\demoCopy\\oldCopy.mp4")
        ){
            // Read and write data
            int b;
            while ((b = fis.read()) != -1) {
                fos.write(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        // Record end time
        long end = System.currentTimeMillis();
        System.out.println("Normal stream replication time:"+(end - start)+" millisecond");
    }

    public static void bufferedCopy() {
        // Record start time
        long start = System.currentTimeMillis();
        // Create flow object
        try (
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream("e:\\demo\\Kobe speech.mp4"));
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("e:\\demoCopy\\newCopy.mp4"));
        ){
            // Read and write data
            int b;
            while ((b = bis.read()) != -1) {
                bos.write(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        // Record end time
        long end = System.currentTimeMillis();
        System.out.println("Buffer stream copy time:"+(end - start)+" millisecond");
    }
}

Operation results:
Buffer stream copy time:3498 millisecond
 Normal stream replication time:319839 millisecond 

After the program runs, you can deeply experience the speed of the buffer flow. The buffer flow has been copied successfully, but the ordinary flow has not been successful. Not only failed, but also took a long time. You can feel that the buffered stream is dozens of times that of an ordinary stream. My video is only 46.2M in size. What if it is a larger file, a few hundred megabytes or even a few gigabytes? Then I can't finish the transmission all day. Isn't this Baidu online disk?

Do you think it's not fast enough and want to experience the feeling of flying. Now I'll take you to the cloud top. Hey, hey, the old driver is going to drive. Don't get carsick.

Next, use the array method to experience:

public class BufferedTest3 {
    public static void main(String[] args) {
    //Use multithreading to test the replication speed of both at the same time.
        new Thread(() -> oldCopy()).start();
        new Thread(() -> bufferedCopy()).start();

    }

    public static void oldCopy() {
        //start time
        long start = System.currentTimeMillis();

        try(
                FileInputStream fis = new FileInputStream("e:\\demo\\Kobe speech.mp4");
                FileOutputStream fos = new FileOutputStream("e:\\demoCopy\\oldCopy2.mp4");
                ) {
            int len;
            byte[] b = new byte[1024];
            while((len = fis.read(b)) != -1) {
                fos.write(b, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        //End time
        long end = System.currentTimeMillis();
        System.out.println("Common stream array copy time:" + (end - start) + "millisecond");
    }

    public static void bufferedCopy() {
        //start time
        long start = System.currentTimeMillis();
        // Create flow object
        try (
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream("e:\\demo\\Kobe speech.mp4"));
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("e:\\demoCopy\\newCopy2.mp4"));
        ){
            // Read and write data
            int len;
            byte[] bytes = new byte[1024];
            while ((len = bis.read(bytes)) != -1) {
                bos.write(bytes, 0 , len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        // End time
        long end = System.currentTimeMillis();
        System.out.println("Buffer stream uses array copy time:"+(end - start)+" millisecond");
    }
}

Program execution results:
Buffer stream uses array copy time:370 millisecond
 Normal stream array copy time: 1016 MS

Is the speed faster? If it's not fast enough, you can change byte[] bytes = new byte[1024] to byte[] bytes = new byte[1024*8]. Can make you experience more efficient. You'll feel the speed flying into the sky.

πŸ‡ Character buffer stream 1.4

πŸ€ 1.4.1 construction method

  • public BufferedReader(Reader in): create a new buffered input stream. The type of the passed in parameter is Reader.

  • public BufferedWriter(Writer out): create a new buffered output stream. The type of the incoming parameter is Writer.

    The demonstration is as follows:

    // Create character buffered input stream
    BufferedReader br = new BufferedReader(new FileReader("e:\\demo\\b.txt"));
    // Create character buffered output stream
    BufferedWriter bw = new BufferedWriter(new FileWriter("e:\\demo\\b.txt"));
    

🐿️ 1.4.2 special methods

It is not used for byte buffer stream and character ordinary stream. It has something that others do not have. What is it? Let's take a look at it now:

  • Character buffer input stream BufferedReader: public String readLine(): read a line of text. If it is read to the end, it will return NULL.

  • Character buffer output stream BufferedWriter: public void newLine(): write a line separator, that is, a new line. The symbol is defined by the system attribute.

    Step by step to demonstrate the following:

    1. public void newLine():

      public class BufferedTest4 {
          public static void main(String[] args) throws IOException {
              BufferedWriter bw = new BufferedWriter(new FileWriter("e:\\demo\\hello.txt"));
      
              //Write data
              bw.write("Hello");
              //Line feed
              //public void newLine()
              bw.newLine();
              bw.write("world");
              bw.newLine();
              bw.write("Java");
              bw.newLine();
              bw.write("newLine");
              bw.flush();
              bw.close();
          }
      }
      
      After the program is executed, view hello.txt The information is:
      Hello
      world
      Java
      newLine
      
    2. public String readLine():

      public class BufferedTest5 {
          public static void main(String[] args) throws IOException {
              BufferedReader br = new BufferedReader(new FileReader("e:\\demo\\hello.txt"));
      
              //Definition get string
              String line = null;
              while((line = br.readLine()) != null) {
                  System.out.println(line);
              }
              br.close();
          }
      }
      
      After the program is executed, view hello.txt The information is:
      Hello
      world
      Java
      newLine
      

πŸ“ 1.5. Text sorting case

What is the text sorting exercise? Let me share my favorite song, and then arrange it in a certain order. Of course, don't worry. There must be a way for you to reorder.

8.Since the target is the horizon
7.I don't think whether there will be cold wind and rain behind me
3.He only cares about the wind and rain
9.What is left to the world is only the back
4.I don't want to win love
5.Since I love roses
6.Just confide your sincerity bravely
10.I don't think about whether the future is flat or muddy
11.As long as you love life
12.Everything is expected
5.Since I love roses
6.Just confide your sincerity bravely
1.I don't think about whether I can succeed
2.Now that you have chosen the distance

"Love life" comes from Wang Guozhen's poetry collection. To be honest, this composition I wrote in high school has always been quoted by me. Not only this one, but also Wang Guozhen's "thank you" and so on. A lt hough I haven't got a particularly high score for my composition so far, it can't hinder my love for Wang Guozhen's works. Just as I wanted to harvest a wisp of spring breeze, you gave me the whole summer. You have to believe that your talent will not be buried forever. So when we cross a high mountain, we cross a real self.

Well, Stop, back to the point: how do we sort this poem.

analysis:

  • Didn't we just learn to read one line in a character buffer stream, so we can read each line of text first.

  • Then don't you have to parse the text? Shall we use the first two rows? It's not advisable to display a few hundred digits of text, but I don't have one line of text.

  • We should see that there is a character "." after the serial number, We can start with this defect. Then store the split serial number and text in the set. For this CP combination, we can use the Map set.

  • Then write the ordered text into the file again.

  • OK, now that we know the idea, let's work together:

    public class BufferedTest6 {
        public static void main(String[] args) throws IOException {
            //Create character input stream object
            BufferedReader br = new BufferedReader(new FileReader("e:\\demo\\Love life.txt"));
    
            //Create character output stream object
            BufferedWriter bw = new BufferedWriter(new FileWriter("e:\\demoCopy\\Love life.txt"));
    
            //Create a Map set to save the data obtained in the future. The key is sequence number and the value is text.
            HashMap<String, String> map = new HashMap<>();
    
            //Read data
            String line = null;
            while((line = br.readLine()) != null) {
                //Pass To split text and sequence numbers
                String[] split = line.split("\\.");
                //Store the obtained data into the set
                map.put(split[0], split[1]);
            }
    
            //Next, don't you get the text by pressing the serial number, that is, the key to find the value
            for (int i = 1; i <= map.size(); i++) {
                String key = String.valueOf(i);
                //Key value finding
                String value = map.get(key);
    
                //If I get the text, I'll write the serial number here. I'm afraid you think I'm ignorant of you. If I believe my classmates, I don't have to write the serial number.
                bw.write(key + "." + value);
                if(i == 7){
                    System.out.println(value);
                }
                //bw.write(value);
                bw.newLine();
                bw.flush();
            }
            bw.flush();
            //Release resources
            bw.close();
            br.close();
        }
    }
    

    After the program runs, as expected, you can see from the file:

    1.I don't think about whether I can succeed
    2.Now that you have chosen the distance
    3.He only cares about the wind and rain
    4.I don't want to win love
    5.Since I love roses
    6.Just confide your sincerity bravely
    7.I don't think whether there will be cold wind and rain behind me
    8.Since the target is the horizon
    9.What is left to the world is only the back
    10.I don't think about whether the future is flat or muddy
    11.As long as you love life
    12.Everything is expected
    

    If you don't want to have a serial number, you can choose not to write the serial number.

πŸ˜— 2. Conversion flow

In the above, we know that when using byte stream to read Chinese, there will be garbled code. Why? What is the encoding format. We used the character stream to manipulate the text at the end. Can we do the conversion between the two? Next, let's learn the origin of this transformation flow in detail.

You can see from the figure that the conversion of bytes and characters is completed through certain encoding and decoding operations. Why is there garbled code? Let's have a look.

πŸ‰ 2.1 character encoding and decoding

The information stored in the computer is represented by binary numbers, and the numbers, English, punctuation marks, Chinese characters and other characters we see on the screen are the result of binary number conversion. According to certain rules, storing characters in the computer is called encoding. On the contrary, the binary number stored in the computer is parsed and displayed according to some rules, which is called decoding. For example, if it is stored according to rule A and parsed according to rule A, the correct text f symbol can be displayed. On the contrary, storing according to rule A and parsing according to rule B will lead to garbled code.

The Java we have learned can be interpreted as:

String(byte[] bytes, String charsetName): Decodes an array of bytes through the specified character set
byte[] getBytes(String charsetName): Encodes a string into a byte array using the specified character set

Generally speaking, I don't know if you have seen the TV play "latent" played by sun Honglei. Even if you haven't seen it, you all know the spy war film. If you and I are both spies, lurking in the enemy camp, and then we have to communicate with each other. You will say a paragraph directly, or send a letter, and then it says: will you meet me on the roof tonight? I promise that if there are teammates like you, they will directly Over and finish it together within a day of latent action. So we can't do this. We need to use certain format rules to convert, right? In this way, even if an enemy gets this letter, he will be confused and think about it... What is it? And then it's Over. The big deal is not to meet tonight, which at least ensures our survival and safety.

  • Among them, we must first have certain rules that can let you and I understand the table data after conversion. We call this rule character coding: it is a set of corresponding rules between natural language characters and binary numbers.

    This table can be equivalent to the conversion rules we refer to, which is called character set (coding table): the corresponding rules between text in life and binary in computer.

  • When you write a letter, this process is to convert what you and I can understand into what no one can understand according to the rules we know. This process is coding.

  • When I get your letter, I will analyze the unreadable text according to the rules. This process is decoding.

  • Among them, if you write to me when you are drunk and don't play cards according to the routine, young people don't talk about martial ethics and write it according to another rule, and then I analyze it according to our rules. After analyzing it, if you can't understand it, you will have a question mark on your face, which can be called garbled code.

So let's first understand the following rule: character set:

  • Charset: also known as code table. It is a collection of all characters supported by the system, including national characters, punctuation marks, graphic symbols, numbers, etc.

    To accurately store and recognize various character set symbols, the computer needs character coding. A set of character set must have at least one set of character coding. Common character sets include ASCII character set, GBK character set, Unicode character set, etc. When we know the encoding format, the corresponding character set will be specified naturally, so the encoding is our final concern.

    The following character sets are relatively complete on the Internet. If you want to know more, you can baidu by yourself. After all, we are programming for Baidu. hey.

    • ASCII character set:
      • ASCII (American Standard Code for Information Interchange) is a set of computer coding system based on Latin alphabet, which is used to display modern English, mainly including control characters (enter key, backspace, line feed key, etc.) and displayable characters (English uppercase and lowercase characters, Arabic numerals and Western symbols).
      • The basic ASCII character set, using 7 bits to represent a character, a total of 128 characters. The ASCII extended character set uses 8 bits to represent one character, a total of 256 characters, which is convenient to support common European characters.
    • ISO-8859-1 character set:
      • Latin code table, alias Latin-1, is used to display the languages used in Europe, including Netherlands, Denmark, German, Italian, Spanish, etc.
      • ISO-5559-1 uses single byte encoding and is compatible with ASCII encoding.
    • GBxxx character set:
      • GB is the meaning of national standard. It is a set of character sets designed to display Chinese.
      • GB2312: Simplified Chinese code table. A character less than 127 has the same meaning as the original. However, when two characters larger than 127 are connected together, they represent a Chinese character, which can be combined with more than 7000 simplified Chinese characters. In addition, mathematical symbols, Roman and Greek letters and Japanese Kanas have been compiled. Even the original numbers, punctuation and letters in ASCII have been re encoded by two bytes, which is often called "full angle" characters, Those below the original number 127 are called "half width" characters.
      • GBK: the most commonly used Chinese code table. It is an extended specification based on GB2312 standard. It uses a double byte coding scheme and contains 21003 Chinese characters. It is fully compatible with GB2312 standard and supports traditional Chinese characters, Japanese and Korean characters.
      • GB18030: latest Chinese code table. It contains 70244 Chinese characters, which are encoded by multiple bytes. Each word can be composed of 1, 2 or 4 bytes. Support the characters of ethnic minorities in China, as well as traditional Chinese characters and Japanese and Korean characters.
    • Unicode character set:
      • Unicode coding system is designed to express any character in any language. It is a standard in the industry, also known as unified code and standard universal code.
      • It uses up to four byte numbers to express each letter, symbol, or text. There are three coding schemes, UTF-8, UTF-16 and UTF-32. The most commonly used UTF-8 coding.
      • UTF-8 encoding can be used to represent any character in Unicode standard. It is the preferred encoding in e-mail, Web pages and other applications for storing or transmitting text. The Internet Engineering Task Force (IETF) requires that all Internet protocols must support UTF-8 coding. Therefore, when we develop Web applications, we also need to use UTF-8 coding. It uses one to four bytes to encode each character. The encoding rules are as follows:
        1. 128 US-ASCII characters, only one byte encoding is required.
        2. Latin and other characters require two byte encoding.
        3. Most common words (including Chinese) are encoded in three bytes.
        4. Other rarely used Unicode auxiliary characters use four byte encoding.

🍊 2.2 garbled code

Why do we read files with garbled code? Because the default encoding format of our editor IDEA is UTF-8, and if our file format is not UTF-8, we will read it incorrectly. Generally speaking, the files created by IDEA are also UTF-8, so there will be no problem in reading and writing. However, if we create files under Windows, The default is ASCII, which will follow the system's default encoding format, which is actually GBK format. Therefore, our file is in GBK format and the read is in UTF-8 format, so it is naturally garbled.


Garbled code under code demonstration:

public class ReaderTest {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("E:\\demo\\China.txt");

        int ch;
        while((ch = fr.read()) != -1) {
            System.out.println((char) ch);
        }

        fr.close();
    }
}

Program execution results:
οΏ½ΠΉοΏ½

Can't you see anything at all? You say you can see, I'm even good at you.

So how do we solve the problem of garbled code, that is, the problem of coding? It's time to sacrifice the conversion stream. It doesn't make you think it's a problem.

πŸ₯­2.3 InputStreamReader

InputStreamReader: input byte stream as character stream. It is a bridge from byte stream to character stream. It reads bytes and decodes them into characters using the specified character set. Its character set can be specified by name, or it can be the default character set, that is, what character set your editor is.

🍌 2.3.1 construction method

  • public InputStreamReader(InputStream in): create a character stream that uses the default character set.

  • public InputStreamReader(InputStream in, String charsetName): creates a character stream with a specified character set.

    The demonstration is as follows:

    public class IpsrTest {
        public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
            InputStreamReader isr = new InputStreamReader(new FileInputStream("e:\\demo\\China.txt"));
    
            InputStreamReader isr2 = new InputStreamReader(new FileInputStream("e:\\demo\\China.txt"), "GBK");
        }
    }
    

🍍 2.3.2 solve the problem of garbled code

public class ReadTest2 {
    public static void main(String[] args) throws IOException {
        String fileName = "E:\\demo\\China.txt";

        //Create conversion stream, default character set
        InputStreamReader isr = new InputStreamReader(new FileInputStream(fileName));

        //Create a conversion stream and specify the character set
        InputStreamReader isr2 = new InputStreamReader(new FileInputStream(fileName), "GBK");

        int ch;
        //Default character set read
        while((ch = isr.read()) != -1) {
            System.out.print((char) ch);
        }

        isr.close();

        //Specify character set reading
        while((ch = isr2.read()) != -1) {
            System.out.print((char) ch);
        }
        isr2.close();
    }
}

Program execution results:
οΏ½ΠΉοΏ½
China

I'm worried that I can't read the documents. It's not good for me to solve the problem. There are read conversion streams and, of course, written conversion streams. Let's have a look.

πŸ‘2.4 OutputStreamWriter

OutputStreamWriter: input byte stream as character stream. It is a bridge from character stream to byte stream. Encodes characters into bytes using the specified character set. Its character set can be specified by name, or it can be the default character set, that is, what character set your editor is.

🍏 2.4.1 construction method

  • public OutputStreamWriter(OutputStream in): create a character stream that uses the default character set.

  • public OutputStreamWriter(OutputStream in, String charsetName): creates a character stream with a specified character set.

    The demonstration is as follows:

    public class WriterTest {
        public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
            OutputStreamWriter osr = new OutputStreamWriter(new FileOutputStream("e:\\demo\\ChinaOut.txt"));
            OutputStreamWriter osr2 = new OutputStreamWriter(new FileOutputStream("e:\\demo\\ChinaOut.txt") , "GBK");
        }
    }
    

🍐 2.4.2 write out the data with the specified code

public class WriterTest2 {
    public static void main(String[] args) throws IOException {
        // Define file path
        String fileName = "E:\\demo\\ChinaOut.txt";
        // Create a stream object with the default UTF8 encoding
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(fileName));
        // Write data
        osw.write("Polaris");
        osw.close();


        String fileName2 = "E:\\demo\\ChinaOut2.txt";
        // Create a stream object and specify the GBK code
        OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream(fileName2),"GBK");
        // Write data
        osw2.write("Call me");
        osw2.close();
    }
}

Results after program execution:
Polaris
 Call me

Looking at the format of Notepad, we can find that if UTF-8 is stored, the format of Notepad is also changed to UTF-8 encoding format, and GBK character set is specified, the format of Notepad is ASCII encoding format.

😚 3. Print stream

I don't know if you have noticed. We usually print the output on the console by calling the print() method and println() method. In fact, they all come from Java io. Printstream class, which is also an IO stream. It can easily print values of various data types. It is a convenient output method.

πŸ§— 3.1 classification

Print stream has only output stream, which is divided into:

  • Byte print stream: printStream.

  • Character print stream: printWriter.

    The specific use methods of the two are basically similar.

🏌️ 3.2 characteristics of print stream

  • Only operate the destination, not the data source.
  • You can manipulate any type of data.
  • If automatic refresh is enabled, it can wrap lines and refresh when calling the println() method.
  • You can directly manipulate text files.

🚣3.3 PrintStream

🚣‍♂️ 3.3.1 construction method

  • public PrintStream(String fileName): creates a new print stream with the specified file name.

    Construction example, code is as follows:

    PrintStream ps = new PrintStream("e:\\demo\\ps.txt");
    

🚣‍♀️ 3.3.2 print to file

We often see system out. Println () is of printStream type when it is printed to the console, but its flow direction is specified by the system and printed on the console. However, since it is a stream object, we can play another function to output data to a specified text file.

public class PrintStreamDemo {
    public static void main(String[] args) throws FileNotFoundException {
        // Call the print stream of the system, and the console outputs 97 directly
        System.out.println(97);

        //Create print stream
        PrintStream ps = new PrintStream("e:\\demo\\ps.txt");

        // Set the print flow direction of the system and output it to ps.txt
        System.setOut(ps);
        // Call the print stream of the system and output 97 in ps.txt
        System.out.println(97);
    }
}

As a result of the program running, you can see that only one 97 is printed on the console. Where is the remaining 97 printed? Check the ps.txt file and you can see that 97 is printed in the file.

🏊 3.3.3 copy file cases

public class PrintStreamDemo2 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("e:\\demo\\ps.txt"));
        PrintStream ps = new PrintStream("e:\\democopy\\psCopy.txt");
        String line;
        while ((line = br.readLine()) != null) {
            ps.println(line);
        }
        br.close();
        ps.close();
    }
}

Program execution results:

🚴3.4 PrintWriter

🚴‍♀️ 3.4.1 construction method

  • public PrintWriter(String fileName): creates a new print stream with the specified file name.

    Construction example, code is as follows:

    PrintWriter pw = new PrintWriter("e:\\demo\\pw.txt");
    

🚡 3.4.2 copy file cases

public class PrintWriterDemo {
    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new FileReader("e:\\demo\\ps.txt"));
        PrintWriter pw = new PrintWriter("e:\\democopy\\pwCopy.txt");
        String line;
        while ((line = br.readLine()) != null) {
            pw.println(line);
        }
        br.close();
        pw.close();
    }
}

Program execution results:

🀸 Essential standard of output flow 5.3

  • The principle of output statement and how to use character stream to output data

    Look directly at a piece of code first:

    public class SystemOutDemo {
        public static void main(String[] args) {
            //There is an out object under the System class, which can obtain the PrintStream output stream object.
            //public final static PrintStream out = null;
            System.out.println("helloworld");
    
            //Output stream object
            PrintStream ps = System.out;
            ps.println("helloworld");
        }
    }
    
    Program execution results:
    All printed on the console:
    helloworld
    helloworld
    
  • Essence:

    Under the System class, there is a static object of public final static PrintStream out = null, which can return a printStream object.

    Therefore, the essence of output statement is IO stream operation, which outputs data to the console.

πŸ˜‡ 4. Serialization

In the byte stream above, we can see two streams: ObjectOutputStream and ObjectInputStream. This stream is mainly used in object serialization. Let's learn about serialization:

For example, the previous operations are related to files and written directly. What we learn is object-oriented. Can we save objects in files. The serialization stream to be learned next is that the object data saved in memory can be transformed into binary data stream for transmission, and any object can be serialized.

Java provides a mechanism for object serialization. An object can be represented by a byte sequence, which contains the data of the object, the type of the object and the attributes stored in the object. After the byte sequence is written out to the file, it is equivalent to persisting the information of an object in the file. Note that you may not understand this file. This file is not for us to read, but to save the information of the object. We can use the byte sequence to read back from the file, reconstruct the object and deserialize it. Object data, object type and attribute information stored in the object can be used to create objects in memory.

🏘️ 4.1 serialization stream ObjectOutputStream

The object is stored in a text file or transmitted in the network in the same way as a stream. Implement persistent storage of objects.

πŸ”οΈ 4.1.1 construction method

  • public ObjectOutputStream(OutputStream out): creates a serialized stream ObjectOutputStream of the specified byte output stream. The parameter passed in is OutputStream byte output stream.

    Construction method demonstration:

    public class ObjectStreamDemo {
        public static void main(String[] args) throws IOException {
            //public ObjectOutputStream(OutputStream out)
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("e:\\demo\\oos.txt")); 
        }
    }
    

⛰️ 4.1.2 serialization operation

How do we implement the serialization of objects?

To realize the serialization of objects, we must not create an object first:

public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Person{name = " + name + ", age = " + age + "}";
    }
}

You also need to know how a method writes the serialized method, right:

public final void writeObject(Object obj) : Writes out the specified object.

At the same time, if an object wants to realize serialization, it needs to meet the following conditions:

  1. This object class must implement Java io. Serializable interface. Serializable can see that there are no methods in it. What's the use? Generally, we call it a tag interface. Classes that do not implement this interface will not serialize or deserialize any state, and will throw NotSerializableException.

    Let's take a look at what happens if it is not implemented:

    public class ObjectStreamDemo {
        public static void main(String[] args) throws IOException {
            //public ObjectOutputStream(OutputStream out)
            // Create serialized stream object
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("e:\\demo\\oos.txt"));
    
            // create object
            Person p = new Person("Test robot 1", 01);
    
            //public final void writeObject(Object obj)
            //Write out objects
            oos.writeObject(p);
    
            // Release resources 
            oos.close();
        }
    }
    

    At this time, the object does not implement the Serializable interface, so after the program runs:

    Exception in thread "main" java.io.NotSerializableException: com.it.test11.Person
    	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
    	at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    	at com.it.test11.ObjectStreamDemo.main(ObjectStreamDemo.java:18)
    

    Indicates that you do not implement the Serializable interface. So let's implement this interface now

    public class Person implements Serializable {
        .....
    }
    

    Now let's take a look at the execution. The operation is normal and there is no exception. Let's take a look at the file information:

    This... Can you understand it? It doesn't matter if you don't understand it, but if there is something you can understand, we can read this file. Let's see how to read it again?

🏚️ 4.2 deserialization stream ObjectInputStream

Restore the stream object data in the text file or the stream object data in the network to an object.

πŸ₯ 4.2.1 construction method

  • public ObjectInputStream(InputStream in): creates a deserialized stream ObjectInputStream of the specified byte input stream. The parameter passed in is InputStream byte input stream.

    The construction method is demonstrated as follows:

    public class ObjectStreamDemo2 {
        public static void main(String[] args) throws IOException {
            //public ObjectInputStream(InputStream in)
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("e:\\demo\\oos.txt"));
        
        }
    }
    

🏦 4.2.2 deserialization

Since we have serialized objects into files before, how can we deserialize file information into objects?

First, we need to know what method can read:

public final Object readObject () : Read an object.

According to our previous operation of reading files, can we get objects in the same way? Let's try it together. To put it bluntly, if you can't, try first. In the process of trying, constantly correct your mistakes, so as to become better.

public class ObjectStreamDemo2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //public ObjectInputStream(InputStream in)
       // Create deserialized object
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("e:\\demo\\oos.txt"));

        // Restore object
        Object obj = ois.readObject();

        // Release resources
        ois.close();

        // Output object
        System.out.println(obj);
    }
}

Program execution results:
Person{name = Test robot 1, age = 1}

🏨 4.2.3 possible problems in deserialization

After we have serialized the object into the file, now we can read it for the first time, right? But if I modify the Person class again. Then what happens when reading?

public class Person implements Serializable {
    private String name;
    private int age;
    private String address;//Add a new attribute
   .....
}

Reread results:

Exception in thread "main" java.io.InvalidClassException: com.it.test11.Person; local class incompatible: stream classdesc serialVersionUID = 1228968110604265735, local class serialVersionUID = 3463310223685915264
	at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1829)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1713)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1986)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1535)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:422)
	at com.it.test11.ObjectStreamDemo2.main(ObjectStreamDemo2.java:14)

You can see a pile of red abnormal information on your console. An InvalidClassException exception occurred. Why did this exception occur. The specific reasons may be as follows:

  • The serial version number of the class does not match the version number of the class descriptor read from the stream
  • The class contains an unknown data type
  • This class has no accessible parameterless constructor

Let's look at the specific reasons for the abnormality:

com.it.test11.Person; local class incompatible: stream classdesc serialVersionUID = 1228968110604265735, local class serialVersionUID = 3463310223685915264

It can be found that after modifying the Person class, the version number of the sequence is inconsistent. Because our modified serial number is not saved in the file again, the latest serial number is inconsistent with the file serial number, resulting in an exception. How can we solve this problem? There are two ways:

  1. Write the file again: after we modify the Person class, we write the file again. We can find that there is no problem after reading again. This method is troublesome. You have to rewrite the file every time you modify it before you can read it again. Is it relatively troublesome? Next, I'll teach you a method once and for all.

  2. Write a fixed version number: since each modification will change the serial version number of the file, we can solve this problem if we can set a fixed serial version number, right. How to set it?

    //Add serial version number
    private static final long serialVersionUID = 2071565876962023344L; 
    

    Just add this in the first line of the Person class. Then we can rewrite it and there is no problem reading it.

🏠 4.3 transient keyword

There may be many member variables in a class, but I don't want to serialize some variables. What should I do?

Just add a keyword transient before the variable name.

  • Transient: transient. Indicates that this variable does not want to be serialized.

    Now, I only want to save the variable of name for the Person class, and I don't want to serialize the variable of age.

    private transient int age;
    

    Now, after rewriting and reading:

    Person{name = Test robot 1, age = 0}
    

    As you can see, age is no longer serialized to the file.

🏑 4.4 set serialization case list

Case: serialize the collection containing multiple user-defined teacher objects and save it to ArrayList Txt file. Deserialize ArrayList Txt, and traverse the collection to print the object information.

How can we realize this case

  1. Create several objects and save them to the collection.
  2. Serialize the collection.
  3. During deserialization reading, you only need to read it once and convert it to collection type.
  4. Traverse the collection, you can print all the teacher information.

OK, now that you know the process, let's implement it directly:

Create the Teacher class and implement the Serializable interface.

package com.it.test12;

import java.io.Serializable;

public class Teacher implements Serializable {
    private String name;
    private int age;


    public Teacher() {
    }

    public Teacher(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Teacher{name = " + name + ", age = " + age + "}";
    }
}

Serialization operation test is in progress.

package com.it.test12;

import java.io.*;
import java.util.ArrayList;

public class ObjectStreamTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //Create teacher object
        Teacher t1 = new Teacher("Miss Wang", 40);
        Teacher t2 = new Teacher("Miss Li", 48);
        Teacher t3 = new Teacher("Miss Zhang", 46);

        //Add to collection.
        ArrayList<Teacher> arrayList = new ArrayList<>();
        arrayList.add(t1);
        arrayList.add(t2);
        arrayList.add(t3);

        //Serialization operation
        serializ(arrayList);

        //The serialization operation is performed first, and then the serialization operation is commented out. Then perform deserialization
//        serializRead();
    }

     //Deserialization operation
    private static void serializRead() throws IOException, ClassNotFoundException {
        ObjectInputStream ois  = new ObjectInputStream(new FileInputStream("list.txt"));
        // Read the object and force it to ArrayList type
        ArrayList<Teacher> list  = (ArrayList<Teacher>)ois.readObject();

        for (int i = 0; i < list.size(); i++ ){
            Teacher s = list.get(i);
            System.out.println(s.getName()+"--"+ s.getAge());
        }
    }

    //Serialization operation
    private static void serializ(ArrayList<Teacher> arrayList) throws IOException {
        // Create serialized stream
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("list.txt"));
        // Write out object
        oos.writeObject(arrayList);
        // Release resources
        oos.close();
    }
}

Results after program running:

Miss Wang--40
 Miss Li--48
 Miss Zhang--46

😢 5. Operate the flow of basic data

For example, we used to operate on data of reference type, such as text of String type, but we haven't encountered a stream that can operate on basic data type, have we. Let's talk about it slowly:

πŸš‹5.1 DataOutputStream

The data output stream enables applications to write raw Java data types to the output stream in a portable manner. The application can then use the data input stream to read the data.

🚌 5.1.1 construction method

  • public DataOutputStream(OutputStream out): create a new data output stream to write data to the specified underlying output stream. The parameter passed in is of type OutputStream.

    Construction example, code is as follows:

    DataOutputStream dos = new DataOutputStream(new FileOutputStream("e:\\demo\\dos.txt"));       
    

🚍 5.1.2 write data

You can see that there are many methods in his source code methods that can operate on data types:

public class DataStreamDemo {
    public static void main(String[] args) throws IOException {
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("e:\\demo\\dos.txt"));

        // Write the data
        dos.writeByte(10);
        dos.writeShort(100);
        dos.writeInt(1000);
        dos.writeLong(10000);
        dos.writeFloat(12.34F);
        dos.writeDouble(12.56);
        dos.writeChar('a');
        dos.writeBoolean(true);

        // Release resources
        dos.close();
    }
}

After the program is executed and written to the file, you can find the file display. You can't understand it. It's not garbled because it's stored here, not for us to read, but for the machine to read. So don't panic. Let's explain reading.

🚎5.2 DataInputStream

Data input streams allow applications to read raw Java data types from the underlying input stream in a machine independent manner. The application uses the data output stream to write data that can later be read by the data input stream.

πŸš‘ 5.2.1 construction method

  • public DataInputStream(InputStream in): creates a DataInputStream that uses the specified InputStream.

    Construction example, code is as follows:

    DataInputStream dis = new DataInputStream(new FileInputStream("e:\\demo\\dos.txt")); 
    

πŸš’ 5.2.2 reading data

You can see that there are many methods in his source code that can read data types:

public class DataStreamDemo2 {
    public static void main(String[] args) throws IOException {
        DataInputStream dis = new DataInputStream(new FileInputStream("e:\\demo\\dos.txt"));

        // Read data
        byte b = dis.readByte();
        short s = dis.readShort();
        int i = dis.readInt();
        long l = dis.readLong();
        float f = dis.readFloat();
        double d = dis.readDouble();
        char c = dis.readChar();
        boolean bb = dis.readBoolean();

        // Release resources
        dis.close();

        System.out.println(b);
        System.out.println(s);
        System.out.println(i);
        System.out.println(l);
        System.out.println(f);
        System.out.println(d);
        System.out.println(c);
        System.out.println(bb);
    }
}

Program execution results:
10
100
1000
10000
12.34
12.56
a
true

😏 6. Random access flow

In our previous learning flow, no matter when reading or writing files, we start from the beginning of the file, and we can't start reading from a specified position. Now we can solve this problem by learning RandomAccessFile.

RandomAccessFile is a special stream in the IO stream system. That is, you can read the contents of the file or write contents to the file. Unlike other input and output streams, you can directly jump to any position of the file to read and write data. So if we want to access only part of the file, we can use the RandomAccessFile class.

Because RandomAccessFile class contains a record pointer to identify the current reading and writing position. When the program creates a new RandomAccessFile object, the file record pointer of the object is located in the file header (i.e. 0). When n bytes are read / written, the file record pointer will move back n bytes. In addition, RandomAccessFile can move the record pointer freely, that is, it can move forward or backward. RandomAccessFile contains the following two methods to manipulate the record pointer of the file

  • long getFilePointer(); Returns the current position of the file record pointer
  • void seek(long pos); Position the file record pointer to the POS position

RandomAccessFile class does not belong to stream, but is a subclass of Object class. But it combines the functions of InputStream and OutputStream. Supports random access, reading and writing to files.

πŸ›°οΈ 6.1 construction method

  • Public RandomAccessFile (File, string mode): creates a random stream. The parameter passed in is the File parameter.
  • public RandomAccessFile(String name, String mode): create a random stream and pass in the String parameter to specify the file name.

Both construction methods need to pass in a specified mode parameter, which specifies the access mode of RandomAccessFile.

Explain separately:

  • r: Opens the specified folder as read-only.
  • rw: open the specified file in read and write mode.
  • rws: the contents of the file to be written and its metadata need to be updated.

  • rwd: only the contents of the file to be written to the storage need to be updated.

    rw mode is commonly used, which can write data or read data.

πŸš€ 6.2 test reading and writing

The reading and writing method is basically the same as the previous byte input and output stream. Let's mainly test the reading method of the specified position:

public class RandomAccessFileDemo {
    public static void main(String[] args) throws IOException {
        RandomAccessFile raf = new RandomAccessFile("e:\\demo\\raf.txt", "r");
        //write file
        write();//helloworld

        //First read
        int ch = raf.read();
        System.out.println((char) ch);
        // The file pointer can be read through the getFilePointer method
        System.out.println("The pointer position of the current file is:" + raf.getFilePointer());

        //Second reading
        ch = raf.read();
        System.out.println((char) ch);
        // The file pointer can be read through the getFilePointer method
        System.out.println("The pointer position of the current file is:" + raf.getFilePointer());


        //What if I want to read the last d directly
        //Set through the seek method.
        raf.seek(9);
        ch = raf.read();
        System.out.println((char) ch);
        // The file pointer can be read through the getFilePointer method
        System.out.println("The pointer position of the current file is:" + raf.getFilePointer());

        raf.close();
    }


    private static void write() throws IOException {
        // Create random access stream object
        RandomAccessFile raf = new RandomAccessFile("e:\\demo\\raf.txt", "rw");

       raf.write("helloworld".getBytes());

       raf.close();
    }
}

Program execution results:
h
 The pointer position of the current file is: 1
e
 The pointer position of the current file is: 2
d
 The pointer position of the current file is: 10

Information stored in file:

😯 7. Attribute set

Finally, let's learn about a persistent attribute set, which uses key value structure to store data. Each key and its corresponding value are a string. This class is also used by many Java classes, such as when obtaining system properties.

🌲7.1 Properties

Inherited from HashTable, it is a Map collection and a collection class that can be used in combination with IO flow.

Since it is both a collection and a collection class that can be used in combination with IO streams.

The specific usage is explained below.

🌳 7.2 construction method

  • public Properties(): create an empty property list.

    The construction demonstration is as follows:

    Properties prop = new Properties();
    

🌴 7.3 test with Map set

public class PropertiesDemo {
    public static void main(String[] args) {
        //Test with Map set
        Properties prop = new Properties();

        prop.put("001", "hello");
        prop.put("002", "world");
        prop.put("003", "Java");

        System.out.println("prop = " + prop);

        for (Object key : prop.keySet()) {
            Object value = prop.get(key);
            System.out.println(key + "::" + value);
        }
    }
}

Program execution results:
prop = {003=Java, 002=world, 001=hello}
003::Java
002::world
001::hello

🌡 7.4 special storage methods

  • public Object setProperty(String key, String value): save a pair of properties. (add element)

  • public String getProperty(String key): use the key specified in this property list to search for property values. (get element)

  • Public set < string > stringpropertynames(): a collection of the names of all keys.

    Code demonstration:

    public class PropertiesDemo2 {
        public static void main(String[] args) {
            //Test special storage functions
            Properties prop = new Properties();
    
            //Add element
            prop.setProperty("001", "hello");
            prop.setProperty("002", "world");
            prop.setProperty("003", "Java");
            // Print property set objects
            System.out.println("prop = " + prop);
            // Get the attribute value through the key
            System.out.println(prop.getProperty("001"));
            System.out.println(prop.getProperty("002"));
            System.out.println(prop.getProperty("003"));
    
            // Traverse the property set to get the collection of all keys
            Set<String> strings = prop.stringPropertyNames();
            // Print key value pairs
            for (String key : strings ) {
                System.out.println(key+" -- "+prop.getProperty(key));
            }
        }
    }
    
    Program running results:
    prop = {003=Java, 002=world, 001=hello}
    hello
    world
    Java
    003 -- Java
    002 -- world
    001 -- hello
    

🌾 7.5 flow related methods

  • Public void load (Reader): read the data in the file into the collection.

  • Public void store (writer, writer, string comments): stores the data in the collection into a file.

    Functions of saving and reading under code demonstration:

    public class PropertiesDemo3 {
        public static void main(String[] args) throws IOException {
            storeTest();
    
            loadTest();
        }
    
        //Public void store (writer, writer, string comments): stores the data in the collection into a file
        private static void storeTest() throws IOException {
            Properties prop = new Properties();
    
            prop.setProperty("Liu Fang", "27");
            prop.setProperty("Liu Yang", "45");
            prop.setProperty("Liu Ci", "37");
            prop.setProperty("Liu Nian", "18");
    
            prop.store(new FileWriter("e:\\demo\\prop.txt"), "");
        }
    
        //Public void load (Reader): read the data in the file into the collection
        private static void loadTest() throws IOException {
            Properties prop = new Properties();
            prop.load(new FileReader("e:\\demo\\prop.txt"));
    
            System.out.println("prop:" + prop);
            Set<String> strings = prop.stringPropertyNames();
            for (String key : strings) {
                System.out.println(key + " -- " + prop.getProperty(key));
            }
        }
    }
    
    Program execution results:
    prop:{Liu Ci=37, Liu Yang=45, Liu Fang=27, Liu Nian=18}
    Liu Ci -- 37
     Liu Yang -- 45
     Liu Fang -- 27
     Liu Nian -- 18
    

    You can view files:

🌿 7.6 small game cases

/**
 * You can only play the number guessing game five times.
 */
public class PlayGameDemo {
    public static void main(String[] args) throws IOException {
        // Load data into a collection
        Properties prop = new Properties();
        prop.load(new FileReader("e:\\demo\\count.txt"));// count=0

        String value = prop.getProperty("count");
        int number = Integer.parseInt(value);

        if (number > 5) {
            System.out.println("The game trial has ended. Please pay to recharge.");
            System.exit(0);
        } else {
            number++;
            prop.setProperty("count", String.valueOf(number));
            Writer w = new FileWriter("e:\\demo\\count.txt");
            prop.store(w, null);
            w.close();

            GuessNumber.start();
        }
    }
}

class GuessNumber {
    private GuessNumber() {
    }

    public static void start() {
        // Generate a random number
        int number = (int) (Math.random() * 100) + 1;

        // Define a statistical variable
        int count = 0;

        while (true) {
            // Enter a data with the keyboard
            Scanner sc = new Scanner(System.in);
            System.out.println("Please enter data(1-100): ");
            int guessNumber = sc.nextInt();

            count++;

            // judge
            if (guessNumber > number) {
                System.out.println("You guessed the data" + guessNumber + "Big");
            } else if (guessNumber < number) {
                System.out.println("You guessed the data" + guessNumber + "Small");
            } else {
                System.out.println("congratulations," + count + "I guessed right once");
                break;
            }
        }
    }
}

When I play in it count>5 and count= 6 When running, it will be displayed
 The game trial has ended. Please pay to recharge.
    

It can be seen that after I played the number guessing game five times, I couldn't play it anymore, and after reading the file, I found count The count value in txt has also reached 6.

🌸 End scattered flowers

I believe all of you have a detailed understanding of the whole IO stream system. In practical application, there are still many drops of IO stream used, but you don't find it! For example, our upload and download, do we need to use IO stream, such as transferring files, so the learning of IO stream is also essential! Only with a solid foundation and a solid chassis can we develop upward.

Let's cheer together! I am not talented. If there are any omissions and mistakes, I also welcome criticism and correction in the comments of talent leaders! Of course, if this article is sure to be of little help to you, please also give some praise and collection to the kind and lovely talent leaders. One key three times. Thank you very much!

Learn here, today's world is closed, good night! Although this article is over, I am still there and will never end. I will try to keep writing articles. The future is long. Why should we fear that cars are far away and horses are slow!

Thank you for seeing here! May you live up to your youth and have no regrets!

Topics: Java Back-end