Java IO stream - detailed introduction to the use of byte stream

Basic introduction to IO stream

Overview of IO streams :

I stands for input, which is the process of reading data from the hard disk file into the memory, which is called input and is responsible for reading.

O means output, which is the process of the data of the memory program from memory to writing out to the hard disk file, called output, responsible for writing.

insert image description here

Classification of IO streams :

Classified by direction:

  • input stream
  • output stream

According to the smallest unit of data in the stream, it is divided into:

  • Byte stream: can operate all types of files ( including audio, video, screen pictures, etc. )
  • Character stream: can only operate on plain text files ( including java files, txt files, etc. )

To summarize the four main categories of streams :

Byte input stream: Based on memory, the stream in which data from disk files/networks is read into memory in the form of bytes is called byte input stream.

Byte output stream: Based on the memory, the stream that writes the data in the memory to a disk file or network in bytes is called a byte output stream.

Character input stream: Based on memory, the stream in which data from disk files/networks is read into memory in the form of characters is called character input stream.

Character output stream: Based on the memory, the stream that writes the data in the memory to a disk file or network medium in characters is called a character output stream.

insert image description here

Use of byte streams

insert image description here

file byte input stream

Create byte input stream

File byte input stream: implement class FileInputStream

Function: Based on the memory, read the data in the disk file into the memory in bytes.

The constructor is as follows :

constructor illustrate
public FileInputStream(File file) Create a byte input stream pipe to connect to the source file object
public FileInputStream(String pathname) Create a byte input stream pipe connected to the source file path

Sample code:

public static void main(String[] args) throws FileNotFoundException {
    
    
  	// 写法一: 创建字节输入流与源文件对象接通
    InputStream inp = new FileInputStream(new File("/file-io-app/src/test.txt"));
}
public static void main(String[] args) throws FileNotFoundException {
    
    
  	// 写法二: 创建字节输入流管道与源文件路径接通
    InputStream inp = new FileInputStream("/file-io-app/src/test.txt");
}

read one byte at a time

method name illustrate
read() Returns one byte at a time, or -1 if there are no more bytes to read

For example, the content of the Notepad file we read is: abcd123

public static void main(String[] args) throws Exception {
    
    
    InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    int a = inp.read();
    System.out.println(a); // 97
    System.out.println((char) a); // a

    // 一次输入一个字节
    System.out.println(inp.read()); // 98
    System.out.println(inp.read()); // 99
    System.out.println(inp.read()); // 100
    System.out.println(inp.read()); // 49
    System.out.println(inp.read()); // 50
    System.out.println(inp.read()); // 51
    // 无字节可读返回-1
    System.out.println(inp.read()); // -1
}

We can loop through the bytes in the file

public static void main(String[] args) throws Exception {
    
    
    InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    int b;
    while ((b = inp.read()) != -1) {
    
    
        System.out.print((char) b); // abcd123
    }
}

Reading one byte at a time has the following problems

slow performance

The problem of garbled characters cannot be avoided when reading Chinese character output.


read an array at a time

method name illustrate
read(byte[] buffer) Each time a byte array is read, the number of bytes read is returned, and -1 is returned if there are no more readable bytes

Define a byte array to receive the number of bytes read

For example, in the following code, the content in the file is: abcd123, three bytes are read each time, and each read will overwrite the content in the previous array, but the third read only reads one character, so only Overwrites the first element of the character array read last time, the result is: 312

public static void main(String[] args) throws Exception {
    
    
    InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    // 定义一个长度为3的字节数组
    byte[] arr = new byte[3];

    // 第一次读取一个字节数组
    int len1 = inp.read(arr);
    System.out.println("读取字节数: " + len1); // 读取字节数: 3
    // 对字节数组进行解码
    String res1 = new String(arr);
    System.out.println(res1); // abc

    // 第二次读取一个字节数组
    int len2 = inp.read(arr);
    System.out.println("读取字节数: " + len2); // 读取字节数: 3
    // 对字节数组进行解码
    String res2 = new String(arr);
    System.out.println(res2); // d12

    // 第三次读取一个字节数组
    int len3 = inp.read(arr);
    System.out.println("读取字节数: " + len3); // 读取字节数: 1
    // 对字节数组进行解码
    String res3 = new String(arr);
    System.out.println(res3); // 312

    // 无字节可读返回-1
    System.out.println(inp.read()); // -1
}

The second parameter of String can specify the start position, and the third parameter can specify the end position. These two parameters can be used to solve the disadvantages of the third read

And the loop improves the optimized code

public static void main(String[] args) throws Exception {
    
    
    InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    byte[] arr = new byte[3];
    int len;
    while ((len = inp.read(arr)) != -1) {
    
    
        String res = new String(arr, 0, len);
        System.out.print(res); // abcd123
    }
}

The disadvantages of reading an array at a time :

Read performance has been improved

The problem of garbled characters cannot be avoided when reading Chinese character output.


Read all bytes at once

To solve the problem of Chinese garbled characters, we can define a byte array as large as the file, and read all the bytes of the file at one time.

Disadvantage: If the file is too large, the byte array may cause memory overflow.

For example, read a file like the one shown below

insert image description here

Method 1 :

Define a byte array by yourself as large as the file size, and then use the method of reading the byte array to complete the one-time reading.

public static void main(String[] args) throws Exception {
    
    
    File file = new File("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");
    InputStream inp = new FileInputStream(file);

    // 创建一个与文件大小一样的字节数组
    byte[] arr = new byte[(int) file.length()];

    // 读取文件, 获取读取的字节长度
    int len = inp.read(arr);
    System.out.println(len); // 252

    // 对字节数组进行解码
    String res = new String(arr);
    System.out.println(res);
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
}

Method 2 :

The official provides the following API for the byte input stream InputStream, which can directly read all the data of the file into a byte array

method name illustrate
readAllBytes() Directly read all the byte data of the file object corresponding to the current byte input stream, then load it into a byte array and return
public static void main(String[] args) throws Exception {
    
    
    InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    // 获取文件的全部字节, 并返回一个字节数组
    byte[] arr = inp.readAllBytes();
    // 对字节数组进行解码
    String res = new String(arr);
    System.out.println(res);
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
}

file byte output stream

Create a byte output stream

File byte output stream: implement class FileOutputStream

Function: Based on the memory, the data in the memory is written out to the disk file in the form of bytes.

The constructor is as follows :

constructor illustrate
FileOutputStream(File file) Create a byte output stream pipe connected to the source file object
FileOutputStream(String filepath) Create a byte output stream pipe connected to the source file path
public static void main(String[] args) throws Exception {
    
    
    // 写法一: 创建输出流与源文件对象接通
    OutputStream oup = new FileOutputStream(new File("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt"));
}
public static void main(String[] args) throws Exception {
    
    
    // 写法二: 创建输出与源文件路径接通(常用)
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

}

write to file output stream

API for writing data out of the file byte output stream :

method name illustrate
write(int a) write a byte out
write(byte[] buffer) write a byte array out
write(byte[] buffer , int pos , int len) Write a portion of a byte array out.

Stream refresh and close API :

method illustrate
flush() Refresh the stream and continue to write data
close() Close the stream, freeing resources, but flushing the stream before closing . Once closed, data can no longer be written

Note: The data must be refreshed when writing data, and the stream needs to be closed after it is used

write a byte out

public static void main(String[] args) throws Exception {
    
    
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    oup.write('a');
    // 支持写入编码
    oup.write(97);
    // 汉字占三个字节, 所以该方法不可以写入汉字
    // oup.write('我');

    // 写数据必须刷新数据
    oup.flush();
    // 刷新流后可以继续写入数据
    oup.write('b');
    // 使用完后需要关闭流, 关闭后不能再写入数据
    oup.close();
}

write a byte array out

public static void main(String[] args) throws Exception {
    
    
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    // 定义一个字节数组
    byte[] arr = {
    
    'a', 98, 'b', 'c'};
    // 写入中文, 需要将中文编码成字节数组
    byte[] chinese = "中国".getBytes();

    // 写入英文字节数组
    oup.write(arr);
    // 写入中文字节数组
    oup.write(chinese);

    // 关闭流(关闭之前会刷新)
    oup.close();
}

write part of a byte array

public static void main(String[] args) throws Exception {
    
    
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    // 定义一个字节数组
    byte[] arr = {
    
    'a', 98, 'b', 'c'};
    // 写入数组的第二个和第三个元素
    oup.write(arr, 1, 2);

    // 关闭流(关闭之前会刷新)
    oup.close();
}

Supplementary knowledge :

Supplement 1: When writing content, if you need to change the line, you can convert it \r\n( window supports input \n but some systems do not support it, use \r\n for versatility ) into a byte array and write it to achieve the effect of line break

public static void main(String[] args) throws Exception {
    
    
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    // 定义一个字节数组
    byte[] arr = {
    
    'a', 98, 'b', 'c'};
    oup.write(arr);
    // 写入换行
    oup.write("\r\n".getBytes());
    // 写入数组的第二个和第三个元素
    oup.write(arr, 1, 2);

    // 关闭流(关闭之前会刷新)
    oup.close();
}

Supplement 2: When writing a file, the original file will be cleared first, and then new data will be written. If we want to add new data based on the original file data, then we need to set the second parameter of the constructor set to true

constructor illustrate
FileOutputStream(File file,boolean append) Create a byte output stream pipeline connected to the source file object, and data can be appended
FileOutputStream(String filepath,boolean append) Create a byte output stream pipeline connected to the source file path, and data can be appended
public static void main(String[] args) throws Exception {
    
    
	  // 设置为true即可
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt", true);
}

file copy exercise

Requirements :

Copy the test.pdf file to the newtest.pdf file in another directory

Idea analysis :

Create a byte input stream object from a data source

Create a byte output stream object based on the destination

Read and write data, copy video

release resources

Sample code :

public static void main(String[] args) {
    
    
    try {
    
    
        // 创建要复制文件的字节输入流
        InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.pdf");
        // 创建目标路径的字节输出流
        OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/newtest.pdf");

        // 使用文件输入流获取要复制文件的全部数据的字节数组
        byte[] arr = inp.readAllBytes();
        // 使用文件输出流将字节数组写入目标文件
        oup.write(arr);
        System.out.println("复制成功!");

        // 释放资源
        inp.close();
        oup.close();
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }
}

Question: What types of files can byte streams copy?

The bottom layer of any file is bytes, and copying is a word-for-word transfer of bytes. As long as the format and encoding of the previous and subsequent files are consistent, there is no problem.
Summary: byte stream is suitable for copying files, but not suitable for Chinese output

Guess you like

Origin blog.csdn.net/m0_71485750/article/details/127592978