Java - I/O (input/output)

1. File class

The java.io package in the File class is the only object that represents the disk file itself. It can create, delete or rename files, determine whether a file exists on the hard disk, query the last modification time of the file, and so on.

Common constructors of the File class

1.1 Create a File object

All constructors need to pass in the path of the file. As shown above, if the program only deals with one directory or file and knows the path of the directory or file, it is more convenient to use the first construction method. If the program deals with several subdirectories or files in a common directory, it is more convenient to use the second or third construction method.

[Case],

It should be noted that the path passed in when creating the File file uses "\\", this is because the directory symbol in windows is a backslash "\", but the backslash is a special character in java, which means escape character, so when using a backslash, a backslash should be added in front, which is "\\". In addition, the directory symbol can also be represented by a forward slash "/", such as: src/Hello.java

import java.io.File;
public class test{
    public static void main (String[] args){
        File f = new File("E:\\Java base\\第七章IO\\a.txt"); //使用绝对路径构造File对象
        File f1=new File("src\\Hello.java"); //使用相对路径构造File对象
        System.out.println(f);
        System.out.println(f1);
    }
}

【operation result】

1.2 Common methods of the File class

The File class provides a series of methods for manipulating the files or directories pointed to by its internally encapsulated path. For example, determine whether a file or directory exists, create or delete a file, etc., as shown in the following figure:

 【Case】

import java.io.File;
import java.io.IOException;
public class test{
    public static void main (String[] args)throws IOException{
        File f = new File("E:\\Java base\\第七章IO\\b.txt"); //使用绝对路径构造File对象
        if(f.exists()){     //如果存在这个文件就删除,否则就创建
            f.delete();
        }else{
            System.out.println(f.createNewFile());
        }
        //在磁盘下创建一层目录,并且在目录下创建文件
        File fileDemo=new File("E:\\Java base\\第七章IO\\hello\\b.txt");
        if(!(fileDemo.getParentFile().exists())){   //判断E:\\Java base\\第七章IO\\hello\目录是否存在
            fileDemo.getParentFile().mkdir();
        }
        if(fileDemo.exists()){      //如果存在这个文件就删除,否则就创建
            fileDemo.delete();
        }else{
            System.out.println(fileDemo.createNewFile());
        }
    }
}

 【operation result】

 1.3 Traverse the files in the directory

The list() method of the File class is used to traverse all the files in the specified directory.

【Case】

import java.io.File;
import java.io.IOException;
public class test{
    public static void main (String[] args)throws IOException{
        //创建File对象
        File f = new File("E:\\Java base\\第七章IO"); 
        if(f.isDirectory()){   //判断File对象对应的目录是否存在
            String[] names=f.list(); //获得目录下的所有文件的文件名
            for (String name:names){
                System.out.println(name); // 输出文件名
            }

        }
    }
}

 【operation result】

The following uses a case to demonstrate how to traverse all files with the extension ".java" in the specified directory.

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
public class test{
    public static void main (String[] args)throws IOException{
        //创建File对象
        File f = new File("E:\\Java base\\第七章IO");
        //创建过滤器对象
        FilenameFilter filter = new FilenameFilter() {
            //实现accept()方法
            public boolean accept (File dir,String name){
                File currFile = new File(dir, name);
                // 如果文件名以.java结尾返回true,否则返回false
                if (currFile.isFile()&&name.endsWith(".java")){
                    return true;
                }else{
                    return false;
                }
            }
        };
        if (f.exists()){  // 判断File对象对应的目录是否存在
            String[] lists=f.list(filter);  //获得过滤后的所有文件名数组
            for(String name:lists){
                System.out.println(name);
            }
        }
    }
}

【operation result】


The previous two cases demonstrate the traversal of the file names of the files in the directory. Sometimes in a directory, in addition to files, there are subdirectories. If you want to get the File class objects in all subdirectories, the list() method obviously cannot meet the requirements. , then you need to use another method listFiles() provided by the FIle class.

The listFiles() method returns an array of File objects. When traversing the elements in the array, if there are subdirectories in the elements that need to be traversed, recursion needs to be used.

【Case】

Call the listFiles() method to store all the subdirectories and files in the directory into an array fires of File type, traverse the array files through the for loop, and judge the currently traversed File object, if it is a directory, call fileDir again The () method performs recursion. If it is a file, it directly prints the path of the output file, thus successfully traversing all the files in the directory.

import java.io.File;
import java.io.IOException;
public class test{
    public static void main (String[] args)throws IOException{
        File file= 
            new File("E:\\Java base\\第七章IO");
            fileDir(file); //调用FileDir方法
    }
    public static void fileDir(File dir){
        File[] files = dir.listFiles(); //获得表示目录下所有文件的数组
        for (File file :files){     //遍历所有的子目录和文件
            if(file.isDirectory()){ 
                fileDir(file); //如果是目录,递归调用fileDir()
            }
            System.out.println(file.getAbsolutePath()); //输出文件的绝对路径
        }
    }
}

【operation result】

This traverses all files

1.4 Delete files and directories

【Case】

import java.io.File;
import java.io.IOException;
public class test{
    public static void main (String[] args)throws IOException{
        File file= new File("E:\\Java base\\第七章IO\\hello");
        if(file.exists()){
            System.out.println(file.delete());
        }
    }
}

【operation result】

The output of the running result is false, which means that the deletion of the file failed. The reason is that the delete() method of the File class can only delete a specified file. If the File object represents a directory, and the directory contains subdirectories or files, then the File class’s The delete() method does not allow to delete this directory directly.

At this time, we need to use recursive way to delete

import java.io.File;
import java.io.IOException;
public class test{
    public static void main (String[] args)throws IOException{
        File file= new File("E:\\Java base\\第七章IO\\hello");
        deleteDir(file); // 调用deleteDir删除方法
    }
    public static void deleteDir(File dir){
        if (dir.exists()){ //判断传入的File对象是否存在
            File[] files=dir.listFiles();   //得到FIle数组
            for(File file:files){  //遍历所有的子目录和文件
                if(file.isDirectory()){
                deleteDir(file);    //如果是目录,则递归调用deleDir()
                }else{
                //如果是文件,则直接删除
                file.delete();
            }
        }
        // 删除完一个目录里的所有文件后,就删除这个目录
        dir.delete();
    }
}
}

【operation result】

It can be found that the directory has been deleted. 

2 byte stream

2.1 The concept of byte stream

In the process of program development, it is often necessary to deal with data transmission between devices, and all files exist in binary (byte) form. Provides a series of streams for byte input/output (I/O) streams. are collectively referred to as byte streams. According to the direction of data transmission, it can be divided into byte input stream and byte output stream.

In the JDK, two abstract classes InputStream and OutputStream are provided. They are the top-level parent classes of byte streams. All byte input streams inherit from InputStream, and all byte output streams inherit from OutputStream. 

In JDK, InputStream and OutputStream provide a series of methods related to reading and writing data, as shown in the following two figures.

The first three read() methods are used to read data. The first read() method reads bytes from the input stream one by one, while the second and third read() methods read several bytes Read in the form of byte array at one time, so as to improve the efficiency of reading data.

When performing I/O stream operations, the current I/O stream will occupy a certain amount of memory, so after the operation is complete, the close() method should be called to close the stream, thereby releasing the system resources occupied by the current I/O stream. 

 The first three are overloaded write() methods, all used to write bytes to the output stream. The first method writes bytes one by one, and the second and third methods write several bytes at once in the form of byte arrays, thereby improving the efficiency of writing data.

The flush() method is used to force the data in the current output buffer (usually a byte array) to be written to the target device. This process is called flushing. The close() method is used to close the stream and release system resources associated with the current I/O stream.

Although the two classes InputStream and OutputStream provide a series of methods related to reading and writing data, these two classes are abstract classes and cannot be instantiated. Therefore, InputStream and OutputStream provide different subclasses for different functions. Classes, these subclasses form an architecture, as shown in the figure below

2.2 InputStream read file

InputStream is the basic input stream provided by JDK. But InputStream is not an interface, but an abstract class. It is the parent class of all input streams. FileInputStream is a subclass of InputStream. It is a byte input stream for operating files and is specially used to read data in files. Since reading data from a file is a repetitive operation, it is necessary to implement continuous reading of data through a loop statement.

The following is a case to realize the reading of file data by byte stream. First, create a text file test.txt in the root directory of the java project, enter the content "itcast" in the file and save it; then use the byte input stream object to read the test.txt text file.

【Case】

import java.io.FileInputStream;
import java.io.IOException;
public class test{
    public static void main (String[] args)throws IOException{
       //创建一个文件字节输入流
       FileInputStream in = new FileInputStream("test.txt");
       int b = 0;   //定义一个int类型的变量b,记住每次读取的一个字节
       while(true){
           b = in.read(); //变量b记住读取的一个字节
           if(b==-1){   //如果读取的字节为-1,跳出while循环
               break;
           }
           System.out.println(b); //否则将b写出
       }
       in.close();
    }
}

 【operation result】

The data in the computer exists in the form of bytes, and each character occupies one byte, so the final result shows the decimal number corresponding to the 6 bytes in the file "test.txt".

105
116
99
97
115
116

Sometimes when the file does not exist, there will be a potential problem in the error message that the console will report, that is, if the file does not exist or other reasons cause an I/O error during the reading process, the InputStream cannot be closed normally, and the resources will also be lost. It cannot be released in time. For this problem, try...finally can be used to ensure that the InputStream can be closed correctly regardless of whether an I/O error occurs.


import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class test{
    public static void main (String[] args)throws IOException{
        InputStream input=null;
        try{
       //创建一个文件字节输入流
       FileInputStream in = new FileInputStream("test.txt");
       int b = 0;   //定义一个int类型的变量b,记住每次读取的一个字节
       while(true){
           b = in.read(); //变量b记住读取的一个字节
           if(b==-1){   //如果读取的字节为-1,跳出while循环
               break;
           }
           System.out.println(b); //否则将b写出
       }
    }finally{
        if(input !=null){
            input.close();
        }
    }
}
}

2.3 OutputStream

OutputStream is the most basic output stream provided by JDK. It is also an abstract class and the parent class of all output streams.

[Case] ​​- How to use FileOutputStream to write data to a file

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Example01 {
    public static void main (String[] args)throws IOException{
        //创建一个文件字节输出流
        OutputStream out = new FileOutputStream("example.txt");
        String str="传智播客";
        byte[] b=str.getBytes();
        for(int i = 0;i<b.length;i++){
            out.write(b[i]);
        }
        out.close();
    } 
}

【operation result】

A new text file "example.txt" will be generated in the directory, but it is garbled after I open it

 2.4 Copying of files

First create two folders source and target in the project, and then store a Song of the Five Rings.doc in the source

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class Example01 {
    public static void main (String[] args)throws Exception{
        //创建一个字节输入流,用于读取当前目录下source文件夹中的文件
        InputStream in = new FileInputStream("source/五环之歌.doc");
        //创建一个文件字节输出流,用于将读取的数据写入target目录下的文件中
        OutputStream out = new FileOutputStream("target/五环之歌.doc");
        int len; //定义一个int类型的变量len,记住每次读取的一个字节
        //获取复制文件前的系统时间
        long begintime = System.currentTimeMillis();
        while((len = in.read())!=-1){ //读取一个字节并判断是否读到文件末尾
            out.write(len); //将读到的字节写入文件
        }
        // 获取文件复制结束时的系统时间
        long endtime = System.currentTimeMillis();
        System.out.println("复制文件所消耗的时间是:"+(endtime-begintime)+"毫秒");
        in.close();
        out.close();
    } 

【operation result】

A doc file is automatically generated in the target 

and the time to transfer the file is 1 millisecond

 When copying files, due to the influence of computer performance and other aspects, the time consumed by copying files will be uncertain. The above-mentioned file copying is to read and write byte by byte, which requires frequent operation of files, and the efficiency is very low. In order to improve efficiency, you can also define a byte array as a buffer. When copying a file, multiple bytes of data can be read at one time and stored in a byte array, and then the data in the byte array can be written to the file at one time.

【Case】

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class Example01 {
    public static void main (String[] args)throws Exception{
        //创建一个字节输入流,用于读取当前目录下source文件夹中的文件
        InputStream in = new FileInputStream("source/五环之歌.doc");
        //创建一个文件字节输出流,用于将读取的数据写入target目录下的文件中
        OutputStream out = new FileOutputStream("target/五环之歌.doc");
        //以下是用缓冲区读写文件
        byte[] buff = new byte[1024]; //定义一个字节数组,作为缓冲区
        // 定义一个int类型的变量len记住读取读入缓冲区的字节数
        int len; 
        //获取复制文件前的系统时间
        long begintime = System.currentTimeMillis();
        while((len = in.read(buff))!=-1){ //读取一个字节并判断是否读到文件末尾
            out.write(buff,0,len); //将读到的字节写入文件
        }
        // 获取文件复制结束时的系统时间
        long endtime = System.currentTimeMillis();
        System.out.println("复制文件所消耗的时间是:"+(endtime-begintime)+"毫秒");
        in.close();
        out.close();
    } 
}

【operation result】

The copying of the file is also realized. During the copying process, the copying of the byte file is gradually realized by using the while loop statement. Every time in the loop, a number of bytes are read from the file to fill the byte array, and the variable len is used to remember the number of bytes read into the array. The number of bytes, and then start from the first byte of the array, write len bytes to the file in sequence, repeating the cycle, when the len value is -1, it means that the end of the culture has been read, and the cycle ends.

2.5 byte buffered stream 

I/O provides two buffered byte streams, namely BufferedInputStream and BufferedOutputStream. Their construction and method respectively receive parameters of type InputStream and OutputStream as objects, and provide buffering function when reading and writing data.

 Let's learn how to use the two streams BufferedInputStream and BufferedOutputStream through the case. First create a src.txt file in the directory, and write some content at will; then create a class, use FileOutputStream in the class to create the file des.txt, and use the byte buffer stream object to transfer the contents of the file src.txt Copy it to the file des.txt.

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class Example01 {
    public static void main (String[] args)throws Exception{
       BufferedInputStream bis = new BufferedInputStream(new FileInputStream("example.txt"));
       BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("des.txt"));
       int len;
       while((len=bis.read())!=-1){
           bos.write(len);
       }
       bis.close();
       bos.close();
    } 
}

3. Character stream

3.1 Character stream definition and basic usage

Like byte streams, character streams also have two abstract top-level parent classes, namely Reader and Writer. Among them, Reader is a character input stream, which is used to read characters from a source device; Writer is a character output stream, which is used to write characters to a target device. As the top-level parent class of character streams, Reader and Writer also have many subclasses. The following lists some commonly used subclasses of Reader and Writer through an inheritance diagram.

 3.2 Character stream operation file

In program development, it is often necessary to read the content of a text file. If you want to read characters directly from a file, you can use the character input stream FileReader. Through this stream, you can read one or a group of characters from the associated file.

Let's use a case to learn how to use FileReader to read the characters of a file

First create a new text file "test.txt" in the directory and enter the character "itcast" in it.

import java.io.FileReader;

public class Example01 {
    public static void main (String[] args)throws Exception{
        // 创建一个FileReader对象用来读取文件中的字符
       FileReader reader = new FileReader("test.txt");
       int ch;  //定义一个变量用于用于记录读取的字符
       while ((ch=reader.read())!=-1){  //循环判断是否读取到文件的末尾
           System.out.println((char)ch); //不是字符流末尾就转为字符打印
       }
       reader.close(); //关闭文件读取流·,释放资源
    } 
}

【operation result】

The function of reading file characters is realized, a FileReader object is created to associate with the file, and then a character is read from the file each time through the while loop and printed, thus realizing the operation of FIleRead reading file characters. It should be noted that the read() method of the character input stream returns a value of type int

 

Guess you like

Origin blog.csdn.net/m0_48936146/article/details/124602114