1. IO system

The Java IO architecture looks like it has a lot of classes and feels complicated, but there are too many factors involved in IO. In the design of IO related classes, the writer is not from the same aspect of consideration, so it will give people a very messy feeling, and the use of design patterns, it is more difficult to use these IO classes, so I specially do a summary of Java IO.

I/O classes are designed to handle I/O-related operations. Where do I/O operations exist? Network, disk. The classes related to network operations are under the JavA.net package and are outside the scope of this article. When you think about disks, you probably think about files, and file operations are typical of IO operations. Introduced in Java is the concept of a “stream,” which represents any object that has the ability to generate or receive a data source. Think of a source of water, sea water, river water, lake water, a glass of water, and so on. Data transmission can be imagined as water transportation. In ancient times, buckets were used to carry water, bamboo pipes were used to carry water, and now steel pipes are used to carry water. Different transportation modes correspond to different transportation characteristics.

From the point of view of the data source or operation object, IO classes can be divided into:

  • 1. File: FileInputStream, FileOutputStream, FileReader, FileWriter
  • Array ([]) :
    • 2.1 ByteArray (byte[]) : ByteArrayInputStream and ByteArrayOutputStream
    • (char[]) : CharArrayReader, CharArrayWriter
  • 3, pipe operation: PipedInputStream, PipedOutputStream, PipedReader, PipedWriter
  • 4, basic data types: DataInputStream, DataOutputStream
  • 5. BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter
  • Print: PrintStream, PrintWriter
  • Object serialization deserialization: ObjectInputStream, ObjectOutputStream
  • 8, conversion: InputStreamReader, OutputStreWriter
  • 9,String (String)Deprecated in Java8:StringBufferInputStream, StringBufferOutputStream, StringReader, StringWriter

Data source nodes can also be reprocessed to make the data easier to use, so they can be divided into node streams and processing streams. This involves design patterns, which will be covered in a later article.

From the point of view of data transmission mode or transportation mode, the IO class can be divided into:

  • 1. Byte stream
  • 2. Character stream

Byte streams are transported in units of bytes, such as a cup of water. And the character stream is transported in multiple bytes, such as a bucket of water, a bucket of water can be divided into several cups of water.

The difference between a byte stream and a character stream

A byte stream reads a single byte, and a character stream reads a single character (a character corresponds to a different byte depending on the encoding, such as three bytes in UTF-8 encoding and two bytes in Chinese encoding). Byte streams are used to process binary files (pictures, MP3s, video files), and character streams are used to process text files (which can be thought of as special binary files with some kind of encoding that can be read by humans). In short, bytes are for computers, characters are for people.

The partition of byte streams and character streams can be seen in the following diagram.

There are a lot of classes in Java IO, but we don’t use all of them. The most common ones are the classes that are related to files, like the basic classes that start with File, the classes that start with Buffered, Deserialize the class starting with Object.

2. IO classes and related methods

There are many IO classes, but the most basic are four abstract classes: InputStream, OutputStream, Reader, and Writer. The most basic methods are read() and write(). The implementation of the method depends on the subclass that inherits the four abstract classes. After all, we usually use subclass objects. Some of these methods are (Native) Native methods, so there is no Java source code, here gives the author think good Java IO source analysis portal, in accordance with the above idea, first look at the basic subclass method, and then look at the subclass also added those methods, I believe you can understand, I’ll just summarize the common classes mentioned above.

InputStream and OutStream are both abstract classes, and most of them are abstract methods. Notice that reading and writing is just getting data and output data.

InputStream class

methods Methods to introduce
public abstract int read() Read the data
public int read(byte b[]) The method of placing the read data in an array of bytes is actually implemented by setting off to 0 and len to the length of the array
public int read(byte b[], int off, int len) Read len bytes from off into a byte array, and the stream ends at -1. (Note that the stream reads one byte, but returns an int of 4 bytes.)link)
public long skip(long n) Skip a specified number of bytes without reading. Think of watching a movie skip the beginning and end of the movie
public int available() Returns the number of readable bytes
public void close() After reading, close the stream and release the resource
public synchronized void mark(int readlimit) Mark the reading location, where you can start reading again next time, to see if the current stream supports it, using the markSupport() method
public synchronized void reset() Resets the read position to the position of the last mark
public boolean markSupported() Determine whether the current stream supports tag streams. Use this method together with the above two methods

OutputStream class

methods Methods to introduce
public abstract void write(int b) If you write a byte, you can see that the parameter is an int. If you write a 32-bit int, only the lower 8 bits are written, and the higher 24 bits are discarded.
public void write(byte b[]) To write all the bytes in the array, similar to the corresponding read() method above, the following method is actually called.
public void write(byte b[], int off, int len) Write len bytes from the off position to the byte array
public void flush() Force refresh to write data from the buffer
public void close() Close the output stream. After the stream is closed, it can no longer output data

If you look at the methods in the Reader and Writer classes, you’ll see that they look a lot like the methods in the two abstract base classes above.

Reader class

methods Methods to introduce
public int read(java.nio.CharBuffer target) Reads bytes into the character cache
public int read() Reading a single character
public int read(char cbuf[]) Reads characters into the specified char array
abstract public int read(char cbuf[], int off, int len) Reads len characters from off into the char array
public long skip(long n) Skip the number of characters of the specified length
public boolean ready() Similar to the available() method above
public boolean markSupported() Determines whether the current stream supports tag streams
public void mark(int readAheadLimit) Mark the reading location, where you can start reading again next time, to see if the current stream supports it, using the markSupport() method
public void reset() Resets the read position to the position of the last mark
abstract public void close() Close the stream to release related resources

Writer class

methods Methods to introduce
public void write(int c) Write a character
public void write(char cbuf[]) Write an array of characters
abstract public void write(char cbuf[], int off, int len) Writes the number of len characters from the off position of the character array
public void write(String str) Write a string
public void write(String str, int off, int len) Writes the number of len characters from the off position of the string
public Writer append(CharSequence csq) Append to inhale a character sequence
public Writer append(CharSequence csq, int start, int end) Appends to part of a sequence of characters, beginning at the start position and ending at the end position
public Writer append(char c) Appends a 16 – bit character
abstract public void flush() Force refresh to write data from the buffer
abstract public void close() Close the output stream. After the stream is closed, it can no longer output data

Let’s use their subclasses directly and introduce the new methods that are not shown below.

1. Read input from the console

import java.io.*;

public class IOTest {
    public static void main(String[] args) throws IOException {
        // Three test methods
// test01();
// test02();
        test03();
    }

    public static void test01(a) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("Please enter one character");
        char c;
        c = (char) bufferedReader.read();
        System.out.println("The character you type is"+c);
    }

    public static void test02(a) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("Please enter one character and press q to end.");
        char c;
        do {
            c = (char) bufferedReader.read();
            System.out.println("The character you type is"+c);
        } while(c ! ='q');
    }

    public static void test03(a) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("Please enter a character line");
        String str = bufferedReader.readLine();
        System.out.println("The character you type is"+ str); }}Copy the code

As for console output, we use it all the time, system.out.println (), and out is actually a reference to an object of the PrintStream class, which also has a write() method, But we use the print() and println() methods more often, because they can print more kinds of content, such as the toString() method of the object that is actually called while one prints an object.

2. Write and read binary files

Note that the path of the file can be changed according to your own situation, although the file suffix here is TXT, but the file is a binary file, and can not be directly viewed.

@Test
    public void test04(a) throws IOException {
        byte[] bytes = {12.21.34.11.21};
        FileOutputStream fileOutputStream = new FileOutputStream(new File("").getAbsolutePath()+"/io/test.txt");
        // Write binary file, open directly will appear garbled
        fileOutputStream.write(bytes);
        fileOutputStream.close();
    }

    @Test
    public void test05(a) throws IOException {
        FileInputStream fileInputStream = new FileInputStream(new File("").getAbsolutePath()+"/io/test.txt");
        int c;
        // Read the written binary file and output an array of bytes
        while((c = fileInputStream.read()) ! = -1) { System.out.print(c); }}Copy the code

3. Write and read text files

The write() and append() methods are not the same as the name of the write() method. One overwrites the content, the other appends the content, and append() is the same as the name of the write() method. The write() method needs to write null as a string, so there is no essential difference. Note that the file encoding is not specified, which may cause garbled characters.

@Test
    public void test06(a) throws IOException {
        FileWriter fileWriter = new FileWriter(new File("").getAbsolutePath()+"/io/test.txt");
        fileWriter.write("Hello, world! \n Welcome to the World of Java \n");
        fileWriter.write("Will not overwrite the original contents of the file \n");
// fileWriter.write(null); Null cannot be written directly
        fileWriter.append("Not to append a line, don't be confused by the method name \n");
        fileWriter.append(null);
        fileWriter.flush();
        System.out.println(The default encoding of the file is + fileWriter.getEncoding());
        fileWriter.close();
    }

    @Test
    public void test07(a) throws IOException {
        FileWriter fileWriter = new FileWriter(new File("").getAbsolutePath()+"/io/test.txt".false); // Disable the append mode and change to the overwrite mode
        fileWriter.write("Hello, world! Welcome to the Java world \n");
        fileWriter.write("I'll overwrite the original contents of the file.");
        fileWriter.append("I'm the next line.");
        fileWriter.flush();
        System.out.println(The default encoding of the file is + fileWriter.getEncoding());
        fileWriter.close();
    }

    @Test
    public void test08(a) throws IOException {
        FileReader fileReader = new FileReader(new File("").getAbsolutePath()+"/io/test.txt");
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        String str;
        while((str = bufferedReader.readLine()) ! =null) {
            System.out.println(str);
        }
        fileReader.close();
        bufferedReader.close();
    }

    @Test
    public void test09(a) throws IOException {
        FileReader fileReader = new FileReader(new File("").getAbsolutePath()+"/io/test.txt");
        int c;
        while((c = fileReader.read()) ! = -1) {
            System.out.print((char) c); }}Copy the code

The InputStreamReader and OutputStreamWriter conversion classes that use byte streams and character streams can specify the encoding of the file and use the buffer-related classes to read each line of the file.

@Test
    public void test10(a) throws IOException {
        FileOutputStream fileOutputStream = new FileOutputStream(new File("").getAbsolutePath()+"/io/test2.txt");
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "GBK"); // Use GBK to encode files
        outputStreamWriter.write("Hello, world! \n Welcome to the World of Java \n");
        outputStreamWriter.append("Another line of content");
        outputStreamWriter.flush();
        System.out.println("The file code is" + outputStreamWriter.getEncoding());
        outputStreamWriter.close();
        fileOutputStream.close();
    }

    @Test
    public void test11(a) throws IOException {
        FileInputStream fileInputStream = new FileInputStream(new File("").getAbsolutePath()+"/io/test2.txt");
        InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "GBK"); // Use GBK to decode files
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String str;
        while((str = bufferedReader.readLine()) ! =null) {
            System.out.println(str);
        }
        bufferedReader.close();
        inputStreamReader.close();
    }
Copy the code

4. Copy files

Here I do some tests, do not use the buffer on the file copy time impact, file copy or file read and write essence. A buffer stream is a processing stream, a decoration to a node stream.

Note: This time was tested on my Asus laptop, just to show that buffering is good for reading and writing files.

@Test
    public void  test12(a) throws IOException {
        // Both inputs and outputs use buffered streams
        FileInputStream in = new FileInputStream("E:\ video \ Big Data \ Principle and Application \1.1 Big Data era. Mp4");
        BufferedInputStream inBuffer = new BufferedInputStream(in);
        FileOutputStream out = new FileOutputStream("1.1 Big Data Era. Mp4");
        BufferedOutputStream outBuffer = new BufferedOutputStream(out);
        int len = 0;
        byte[] bs = new byte[1024];
        long begin = System.currentTimeMillis();
        while((len = inBuffer.read(bs)) ! = -1) {
            outBuffer.write(bs, 0, len);
        }
        System.out.println("Time required to copy files:" + (System.currentTimeMillis() - begin)); // The average time is more than 200 milliseconds
        inBuffer.close();
        in.close();
        outBuffer.close();
        out.close();
    }


    @Test
    public void  test13(a) throws IOException {
        // Only input uses the buffered stream
        FileInputStream in = new FileInputStream("E:\ video \ Big Data \ Principle and Application \1.1 Big Data era. Mp4");
        BufferedInputStream inBuffer = new BufferedInputStream(in);
        FileOutputStream out = new FileOutputStream("1.1 Big Data Era. Mp4");
        int len = 0;
        byte[] bs = new byte[1024];
        long begin = System.currentTimeMillis();
        while((len = inBuffer.read(bs)) ! = -1) {
            out.write(bs, 0, len);
        }
        System.out.println("Time required to copy files:" + (System.currentTimeMillis() - begin)); // The average time is more than 500 milliseconds
        inBuffer.close();
        in.close();
        out.close();
    }

    @Test
    public void test14(a) throws IOException {
        // Neither input nor output uses a buffered stream
        FileInputStream in = new FileInputStream("E:\ video \ Big Data \ Principle and Application \1.1 Big Data era. Mp4");
        FileOutputStream out = new FileOutputStream("1.1 Big Data Era. Mp4");
        int len = 0;
        byte[] bs = new byte[1024];
        long begin = System.currentTimeMillis();
        while((len = in.read(bs)) ! = -1) {
            out.write(bs, 0, len);
        }
        System.out.println("Time required to copy files:" + (System.currentTimeMillis() - begin)); // The average time is over 700 milliseconds
        in.close();
        out.close();
    }

    @Test
    public void test15(a) throws IOException {
        // Do not use buffering
        FileInputStream in = new FileInputStream("E:\ video \ Big Data \ Principle and Application \1.1 Big Data era. Mp4");
        FileOutputStream out = new FileOutputStream("1.1 Big Data Era. Mp4");
        int len = 0;
        long begin = System.currentTimeMillis();
        while((len = in.read()) ! = -1) {
            out.write(len);
        }
        System.out.println("Time required to copy files:" + (System.currentTimeMillis() - begin)); // The average time is about 160,000 milliseconds, about 2 minutes
        in.close();
        out.close();
    }
Copy the code

For serialization and deserialization, here’s my previous blog, Portal. Summary: Java IO classes are many, but grasp the whole system, grasp the key method, learning will be much easier, after reading this article, do you think Java IO is not so difficult as you think? Let us know in the comments below.

Welcome to follow the public wechat account below, in addition to a variety of learning materials to share for free!