Java notes - IO (concept, method, instance)

Keywords: Java Back-end io

Related concepts of IO

IO: it is used to solve the problem of data transmission between devices
Stream is an abstract and dynamic concept. It is a series of continuous and dynamic data sets. It is a group of sequential byte sets with starting and ending points. Flow is like water in a pipe connecting files and programs. It is an abstraction of data transmission.
Java operates on data through stream. The objects used for the operation flow are all in the IO package

Divided by flow direction:

  1. Input stream
  2. Output stream OuputStream

By data type:

  1. Byte stream InputStream / OutputStream
    The byte stream performs input or output operations in bytes
    InputStream byte input stream: read data. Abstract class is the parent class of all input streams. It defines the common characteristics of all input streams.
    OutputStream byte output stream: write out data. Abstract class, which is the parent class of all output streams. The common characteristics of all output streams are defined.
  2. Character stream Reader / Writer
    The character stream maps characters in character units according to the ASCII code table
    Reader character input stream: read data, abstract class
    Writer character output stream: write data, abstract class

When to use byte stream and character stream?

Whenever dealing with plain text data, character streams are preferred. In addition, byte streams are used.
Text files, videos and pictures are stored in bytes in the computer, so you can use the Notepad provided by windows to open the data files to be uploaded or downloaded. If the contents can be understood, use character stream. If you don't understand, use byte stream.

Byte input stream FileInputStream

FileInputStream is a subclass of InputStream, which can read data from the file stream.
This is the description of the function of FileInputStream in the jdk document

Construction method:
FileInputStream(File file)
FileInputStream(String name)

Read mode:
  1. int read()
    Read one byte of data from the input stream.
    Read the next byte of the input stream and return the int value represented by bytes (0 ~ 255). A byte is eight bits, binary 11111111 is converted to decimal 255
  2. int read(byte[] b)
    The data of up to b.length bytes read from the input stream is a byte array.
package review.IO;

import java.io.FileInputStream;
import java.io.IOException;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("a.txt");
        System.out.println(fis.read()); //97
        System.out.println((char)fis.read()); //b. Byte a that has been read will not be read repeatedly, so it is B


        //Reading like the above is too slow. Use the while loop to improve
        //When the end is read, the fis.read() statement returns - 1
        int n = 0;
        while((n=fis.read())!=-1){
            System.out.print((char)n); //cdefg
        }
        //Close flow
		fis.close();
    }
}

package review.IO;

import java.io.FileInputStream;
import java.io.IOException;

public class Demo2 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("a.txt");
        //The array length is 1024, which is more appropriate. It will not be too long, waste resources or too short
        byte[] bytes = new byte[1024];
        int len;
        //Use len to receive the actual read byte length of fis.read(byte[] b)
        //Returns - 1 when reading to the end of the file
        //(len =fis.read(bytes) note that it is enclosed in parentheses
        //Here, s will not be printed after reading one byte, because it reads one byte array at a time
        while((len =fis.read(bytes))!=-1){
            //The length here is from 0 to len, and the array is converted to String type according to the number of bytes actually read
            String s = new String(bytes,0,len);
            System.out.println(s); //The result is abcdefg
        }
        fis.close();
    }
}

Byte output stream FileOutputStream

FileOutputStream is the concrete implementation class of OutputStream
Construction method:
FileOutputStream(File file)
FileOutputStream(String name)

Write mode
  1. void write(int b) writes the specified bytes to this file output stream.
  2. void write(byte[] b) writes b.length bytes from the specified byte array to the file output stream.
  3. write(byte[] b, int off, int len) writes len bytes to the file output stream from the specified byte array at offset off.
package review.IO;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo3 {
    public static void main(String[] args) throws IOException {
        //Construction method 1, which is usually used
        FileOutputStream fos = new FileOutputStream("b.txt");
        //Construction method II
        File f = new File("a.txt");
        FileOutputStream fos1 = new FileOutputStream(f);

        //write(int b)
        fos.write(97);
        fos.write(98);
        //Write a newline character, otherwise all characters written are on the same line
        fos.write("\r\n".getBytes());
        
        //getBytes() stores the string in the character array
        //write(byte[] b)
        fos.write("hello java".getBytes());
        fos.write("\r\n".getBytes());

        byte[] bys = {97,98,99,100,101};
        //Read three bytes from the index 1 position of the array and write them to the file
        fos.write(bys,1,3);

        fos.close();

    }
}

Realize data addition

FileOutputStream(File file, boolean append)
The append parameter in FileOutputStream is false by default, that is, each time data is written to the file, the original content in the file will be overwritten
After changing the append parameter to true, it will be modified to append content to the original content in the file

 FileOutputStream fos = new FileOutputStream("b.txt",true);

Modify the above code to construct the FileOutputStream object
The result is

Append to the original content instead of overwriting the original content

Byte buffered input stream BufferedInputStream

When we used InputStream to read the data in the file, we found that reading with a byte array is much more efficient and fast than reading one byte at a time. This idea is used in the byte buffer stream by java. The existence of the buffer stream is to read the data into the buffer stream (memory) first , and then read multiple characters from memory at one time, so as to improve the efficiency of reading.

The decorator mode is actually used here. See this blog for details
FilterInputStream and FilterOutputStream analysis of Java IO streams

BufferedInputStream is essentially implemented through an internal buffer array When reading the data of the input stream, BufferedInputStream will fill the data of the input stream into the buffer in batches. Every time the data in the buffer is read, the input stream will fill the data buffer again; this is repeated until we finish reading the data position of the input stream.

Construction method:

  1. BufferedInputStream(InputStream in)
  2. BufferedInputStream(InputStream in, int size) specifies the buffer size

The InputStream in parameter here actually passes in the specific implementation class of InputStream when creating the object

package review.IO;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class Demo4 {
    public static void main(String[] args)throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
        int len = 0;
        byte[] bytes = new byte[1024];
        while((len=bis.read(bytes))!=-1){
            String s = new String(bytes,0,len);
            System.out.println(s); //The read result is abcdefg
        }
        bis.close();
    }
}

Byte buffered output stream BufferedOutputStream

The function of flush() is to refresh the buffer and write the contents of the buffer to the file

The difference between flush() and close():
1. The close() method call closes the stream object. However, the buffer will be flushed first. After closing, the stream object can no longer be used
2. After the flush() method is called, the buffer is refreshed once, but the stream object can continue to be used

When using the buffered output stream to write data to the file, at least one of flush and close can write the data to the file. Otherwise, the data will always exist in the buffer until the buffer is full, and then it will be written automatically

package review.IO;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo5 {
    public static void main(String[] args) throws IOException {
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.txt"));
        bos.write("Hello, hello".getBytes());
        //flush outputs the contents of the buffer directly without waiting for the buffer to be full
        bos.flush();
        bos.close();
    }
}

Conversion flow

When there is Chinese in the file content, if we only read one byte and output this byte, we will find that the output result is garbled

package review.IO;

import java.io.FileInputStream;
import java.io.IOException;

public class Demo6 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("a.txt");
        int b = 0;
        while((b=fis.read())!=-1){
            System.out.print((char)b);
        }

    }
}

The read result is

It is a string of garbled code, because Chinese occupies more than one byte, and multiple bytes can form a Chinese character. If you separate one byte, you will find that the output is garbled code

Because of this, it is very inconvenient for byte stream to operate Chinese, so character stream is needed
Character stream is based on byte stream, which can provide character level encoding and decoding
The conversion stream establishes a bridge from byte stream to character stream. It is a processing stream and provides the conversion between byte stream and character stream.
Java provides two transformation streams: InputStreamReader and OutputStreamWriter, both of which belong to character streams.
InputStreamReader flows byte input into character input stream, which is inherited from Reader.
OutputStreamWriter transfers character output to byte output stream, which is inherited from Writer.

In the computer, the data is stored in binary form. The text information we actually see is displayed after binary data conversion. There is a relationship between encoding and decoding.
Encoding: similar to the process of encryption, it converts understandable characters or strings into incomprehensible bytes. String – byte[]
Decoding: similar to the process of decryption, the process of converting incomprehensible bytes into understandable characters or strings. byte[] – String

Character stream can actually be understood as conversion stream. Character stream = byte stream + encoding table.

package review.IO;

import java.io.IOException;
import java.util.Arrays;

public class Demo7 {
    public static void main(String[] args) throws IOException {
        String s = "Hello world";

        //byte[] getBytes(Charset charset)
        //Use the given charset to encode the String into a byte sequence and store the result in a new byte array.
        //String -- byte[]
        byte[] bytes =s.getBytes("UTF-8");
        System.out.println(Arrays.toString(bytes));

        //String(byte[] bytes, Charset charset)
        //Construct a new String and decode charset with the specified array of bytes
        //byte[] -- String
        String ss = new String(bytes,"UTF-8");
        System.out.println(ss);
    }
}

The result is

UTF-8 in brackets can be replaced with Unicode or GBK, but it should be noted that the charset encoding table used for encoding and decoding should be the same

Character output stream OutputStreamWriter (character conversion stream)

OutputStreamWriter write data method
public void write(int c)
public void write(char[] cbuf)
public void write(char[] cbuf,int off,int len)
public void write(String str)
public void write(String str,int off,int len)
Note: starting from the character stream, a character array is read at one time instead of a byte array. Array with char []

package review.IO;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class Demo8 {
    public static void main(String[] args) throws IOException {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"));
        //write(int c)
        osw.write(97); //a

        //write(char[] cbuf) writes a character array
        char[] chars = {'a','b','c','d','e'};
        osw.write(chars); //abcde

        //write(char[] cbuf,int off,int len) writes a part of the character array to a file
        char[] chars1 = {'a','b','c','d','e'};
        //Read two characters from subscript 1
        osw.write(chars1,1,2); //bc

        //write(String str) writes a string to a file
        osw.write("hello"); //hello

        //write(String str,int off,int len) writes part of the string to a file
        String s2 = "hadoop";
        osw.write("hadoop",1,2); //ad

        osw.flush();
        osw.close();
    }
}

Character input stream InputStreamReader

  1. InputStreamReader(InputStream in)
    Read the data and convert the byte stream into character stream according to the default encoding
    Create an InputStreamReader that uses the default character set.
  2. InputStreamReader(InputStream in, String charsetName)
    Read the data and convert the byte stream into character stream according to the specified encoding
    Creates an InputStreamReader that uses the specified character set.

How to read data:

  1. public int read(): read only one character at a time
  2. public int read(char[] cbuf): read one character array at a time
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class Demo9 {
    public static void main(String[] args) throws IOException {
        //InputStream in = new FileInputStream("a.txt)
        InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));

        //Read only one character at a time
        int ch = 0;
        while((ch=isr.read())!=-1){
            System.out.println((char)ch);
        }
        isr.close();
    }
}

The result is

You can find that the console outputs Chinese characters instead of numbers of type int

public class Demo9 {
    public static void main(String[] args) throws IOException {
        //InputStream in = new FileInputStream("a.txt)
        InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));

        //Read multiple characters at a time, that is, read a character array
        char[] chars = new char[1024];
        int len = 0;
        while((len=isr.read(chars))!=-1){
            System.out.println(new String(chars,0,len));
        }

        isr.close();

    }
}

A simple writing method of character conversion stream

Character stream = byte stream + encoding table
OutputStreamWriter = FileOutputStream + encoding table (Unicode)
InputStreamReader = FileInputStream + encoding table (Unicode)

Simple writing method of character output stream OutputStreamWriter FileWriter
Character input stream InputStreamReader simple writing method FileReader

package review.IO;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Demo11 {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("a.txt");
        FileWriter fw = new FileWriter("b.txt");

        int len = 0;
        char[] chars = new char[1024];
        while((len=fr.read(chars))!=-1){
            fw.write(chars,0,len);
            fw.flush();
        }
        
        fw.close();
        fr.close();
    }
}

As a result, the contents of a.txt were successfully written to b.txt

Note: when multiple streams need to be closed in the program, close them from bottom to top.
For example, FR is opened first and fw is opened later. When closing, close fw first and then fr

Character buffered input stream BufferedReader

In order to read and write efficiently, the character stream also provides the corresponding character buffer stream
BufferedWriter: character buffered output stream
BufferedReader: character buffered input stream

BufferedReader(Reader in) creates a buffered character input stream using a default size input buffer.

package review.IO;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class Demo10 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        //1, Read one character at a time
        int ch = 0;
        while((ch=br.read())!=-1){
            System.out.println((char)ch);
        }

        //2, Read one character array at a time
        int len = 0;
        char[] chars = new char[1024];
        while((len=br.read(chars))!=-1){
            System.out.println(new String(chars,0,len));
        }
        br.close();
    }
}

The results are respectively (note that the two pieces of code should be run separately, otherwise the reading content of the second piece of code is empty, which is put together for the sake of intuition)

Character buffered output stream BufferedWriter

BufferedWriter: character buffered output stream
Writes text to the character output stream, buffering characters to provide efficient writing of individual characters, arrays, and strings.
You can specify the buffer size, or you can accept the default size.
The default value is large enough for most purposes.

Creation method:

  1. BufferedWriter(Writer out) creates a buffered character output stream using an output buffer of the default size
  2. BufferedWriter(Writer out, int sz) creates a new buffered character output stream using an output buffer of a given size.
package review.IO;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class Demo12 {
    public static void main(String[] args) throws IOException {
        /*
            BufferedWriter bw = new BufferedWriter(
                       new OutputStreamWriter(new FileOutputStream("b.txt)));
            This is the original writing method. It is really complex. You need to create a byte output stream FileOutputStream
            Then use OutputStreamWriter to stream byte output into character output stream
            Then the function of adding the character output stream to the buffer becomes BufferedWriter
         */

        BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));

        bw.write(97); //a
        bw.write(98); //b

        bw.write("hello"); //hello
        bw.write("hadoop",1,2); //ad

        char[] chars = {'a','b','c','d'};
        bw.write(chars); //abcd
        bw.write(chars,1,2); //bc

        bw.flush();
        bw.close();
    }
}

Special method

Special method of character buffer stream:
BufferedWriter -- public void newLine() writes a line separator for line feed
BufferedReader -- public String readLine() reads a line of text until the newline character terminates, and then reads the next line

package review.IO;

import java.io.*;

public class Demo13 {
    public static void main(String[] args) throws IOException {
		write();
        read();
    }

    public static void read() throws IOException{
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        String line = null;
        //(line=br.readLine()) read one line of the file to line each time, and then execute the print statement in the while loop body
        //So print one line at a time
        while((line=br.readLine())!=null){
            System.out.println(line);
        }
        br.close();
    }

    public static void write() throws IOException{
        BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
        for(int i=0;i<10;i++){
            bw.write("The second step of learning big data "+i+" day");
            //newLine() changes to the next line after each sentence is written
            bw.newLine();
            bw.flush();
        }
    }
}

The result of running the write () method

The result of using the read () method

Posted by chatmaster on Thu, 21 Oct 2021 08:40:50 -0700