Detailed parsing of I/O operations

Posted by illzz on Sat, 18 May 2019 13:23:52 +0200

I/O operations

Article Directory

1: File operation

File class does not manipulate file contents

1. Determine whether the file exists

        File file = new File("E:\\File Test\\Test 2");
        System.out.println(file.exists());  //true
  • This is a path, so the exists method is to determine if it exists, not whether it is a file?

2. Determine whether it is a file

        File file = new File("E:\\File Test\\Test 2");
        System.out.println(file.isFile());   //false
  • Here, E:\File Test\Test 2 is a folder, so it is false

3. Create and delete files

        File file = new File("E:\\File Test\\Test 2\\lala");
        if(file.createNewFile()) {
            System.out.println("create file success!");
        }else {
            System.out.println("create file fail");
        }
        System.out.println(file.isFile());  //true
  • In this code, E:\File TestTest 2 is a path we already have under windows. When you do this, you will automatically create a new lala.txt text document under Test 2. When you do not specify the new file format, it defaults to a text document. If the file already exists, it will fail to create.
  • So the File class provides createNewFile to create a file, not a folder or path;
  • To delete a file, for File class: delete () method, the return value is boolean, just like creating a file;

4. Create a directory

File provides: public boolean mkdirs()

        File file = new File("E:\\File Test\\Test 3\\Test 3-1");
        if(file.mkdirs()) {
            System.out.println("Successful directory creation");
        }else {
            System.out.println("Failed to create directory");
        }
  • Originally, we did not test 3 under the file test, nor test 3-1. After executing the above, a new folder named test 3 was created in the file test directory, and a new folder named test 3-1 was created in the test 3 folder. Note that all the new folders are created here.
  • The File class also provides the following: public boolean mkdir(), which differs from the above method in that when the parent directory of a file object does not exist, the path creation fails, whereas the mkdirs method creates all parent paths regardless of whether or not the parent path exists, or if it does not exist;

2: I\O Flow Operation

File class does not support file content processing, if you want to process file content, you must do so through the operation mode of the stream.The flow is divided into input and output streams.

In a java.io package, streams are divided into two types: byte streams and character streams

  1. Byte Stream: InputStream, OutputStream
  2. Character stream: Reader, Writer

OutPutStream and InputStream are abstract classes, so they cannot be used directly to create objects. You need to use their subclasses to see their definitions:

public abstract class InputStream implements Closeable
public abstract class OutputStream implements Closeable, Flushable 

Closeable is the interface for close, and Flushable is for flush (refresh on write, read unnecessary)

1. (1) OutputStream with byte streams

OutPutStream and InputStream are abstract classes, so they cannot be used directly to create objects. You need to use their subclasses to see their definitions:

//If the test is E:\File Test\Test, an error will be compiled and the path must be a specific file, not a folder
		File file = new File("E:\\File Test\\test\\hello.txt");
//First way of writing:
        //When writing data, it is important to determine if the parent path exists and create it for him if it does not.
//        if(!file.getParentFile().exists()) {
//            file.getParentFile().mkdirs();
//        }
//        OutputStream out = new FileOutputStream(file);
//        String str = "i love you";
//        byte[] buff = str.getBytes();
//        out.write(buff);
//        out.flush();
//        out.close();

//Second way of writing:
        if(!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        try(OutputStream out = new FileOutputStream(file)){
            String str = "i love you";
            byte[] buff = str.getBytes();
            out.write(buff);
            //Refresh cache, preferably write
            out.flush();
        }catch(IOException e) {
            e.printStackTrace();
        }
  • For IO operations, which belong to resource processing, all resource processing operations (IO operations, database operations, networks) must be closed at last. The difference between the first and the second is: the first is to close manually, and the second is to add an AutoCloseable interface from JDk1.7. The main purpose of this interface is to automatically close the operations and use it must be finalizedHe try...catch;

  • When manipulating the byte output stream, the given file object must be of file type (), that is, not a folder. If the file does not exist (provided that the parent directory of the file must exist), the file will be created automatically, that is, it will not be created using the createNewFile method;

  • When writing, each time it is executed, the target is written to the file empty, and then written. If you want to preserve the contents of the target written to the file and continue adding the contents, you need to call another parametric construct when you create the OutputStream class object, that is, (the code above only uses this location.)

     OutputStream out = new FileOutputStream(fileļ¼Œtrue)
    

1. (2) Write using a character output stream (Writer)

public abstract class Writer implements Appendable, Closeable, Flushable

This class implements three interfaces, with more Appendable interfaces than byte output streams
This class also has write methods, as shown below.

    public void write(String str) throws IOException 

Character output streams are almost identical to byte output streams in how they are used,**The biggest difference is that the provider's write method can write directly with a string as a parameter, without converting to bytes,** In addition to these other uses, which are essentially unchanged, as an abstract method, we need to instantiate the object with a subclass of File Writer.

        File file = new File("E:\\File Test\\Test 2\\test.txt");
        try(Writer writer = new FileWriter(file,true)) {
            writer.write("i like you dream!!!"); 
        }catch (IOException e) {
            e.printStackTrace(); 
        }

2. Read data using byte input streams

Actually, the input and output are almost the same. The code is directly shown here:

        File file = new File("E:\\File Test\\Test 2\\test.txt");
        try(InputStream in = new FileInputStream(file)) {
            byte[] arr = new byte[10];
            //If int len = in.read(arr) is defined here first, the following while condition will be read from the second time.
            int len = -1;
            while((len = in.read(arr)) != -1) {
                String str = new String(arr,0,len);
                System.out.println(str);
            }
        }

In the example above, the byte array we defined is used to accept byte data for each read. You can set the size of the array at will, but it is usually 1024*1024. Here we have selected 10 for the highlight feature. If we don't have this while loop to read all the time, one read is not complete.

  • When the read is complete, the read function returns -1,
  • At the end of each read, the next read continues where the last one ended!

3. File copy instance code (contains detailed operations for reading and writing)

package com.bitten.file;
import java.io.*;
/**
 * @Author : YangY
 * @Description : File Copy
 * @Time : Created in 16:33 2019/3/31
 */
public class FileCopyUtil {
    public static void main(String[] args) {
        //destFilePath must be a path to a specific file, not a folder;
        cp("E:\\File Test\\test\\hello.txt","E:\\File Test\\Test 2\\test.txt");
    }

    /**
     *
     * @param sourceFilePath:source file
     * @param destFilePath: Destination File
     */
    public static void cp(String sourceFilePath,String destFilePath) {
        checkArgumentNotNull(sourceFilePath,"souce file path must not be NULL!!");
        checkArgumentNotNull(destFilePath,"dest file path must not be NULL!!");
        File souceFile = new File(sourceFilePath);
        checkFile(souceFile,"SouceFile must not be null!!");
        File destFile = new File(destFilePath);
        checkDestFile(destFile);
        dataCopy(souceFile,destFile);

    }
    public static void checkArgumentNotNull(Object args, String msg) {
        if(args == null ) {
            throw new IllegalArgumentException(msg);
        }
    }

    private static void checkDestFile(File file) {
        //If the parent directory does not exist, copy ing fails. To avoid this, we create a parent directory for it if it does not exist.
        if(!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
    }

    private static void checkFile(File file,String msg) {
        //The source file cannot be empty and must be a file, not a directory, and an exception must be thrown.
        if(file == null || !file.exists() ) {
            throw new IllegalArgumentException(msg);
        }
    }

    /**
     * Really Implement Copy Method
     * @param souce
     * @param dest
     */
    private static void dataCopy(File souce, File dest) {
        long start = System.currentTimeMillis();
        try(InputStream in = new FileInputStream(souce);
            OutputStream out = new FileOutputStream(dest);
        ){
            byte[] buff = new byte[1024*1024];  //1024*1024 bytes per transfer, or 1M
            int length = -1;
            //When the read method returns a value of -1, it means that the data has been read;
            while((length=in.read(buff)) != -1) {
                out.write(buff,0,length);
            }
            out.flush();
            long end = System.currentTimeMillis();
            System.out.println("COPY SUCCESS!!!"+"Time consuming:"+(end-start));
        }catch(IOException e) {
            e.printStackTrace();
        }
    }
}

4. Conversion Flow

In Java, classes that convert byte streams to character streams are also provided:

OutputStreamWriter: Convert byte output stream to character output stream (Writer is more convenient for text output than OutputStream) InputStreamReader: Convert byte input stream to character input stream (InputStream reads bytes, which is not convenient for Chinese processing)

Look at the definitions of these two classes:

public class OutputStreamWriter extends Writer
public class InputStreamReader extends Reader

We can see their inheritance as an understanding

5. Character encoding

Understanding: There is only one encoding used in development: UTF-8

6. Memory Flow

There are also two types of memory streams:

  1. Byte memory stream: ByteArrayInputStream, ByteArrayOutputStream
  2. Character memory stream: CharArrayReader, CharArrayWriter

Let's look at an example of merging two files:

package com.bitten.file;

import java.io.*;

/**
 * @Author : YangY
 * @Description :  Merge two files
 * @Time : Created in 19:06 2019/4/5
 */
public class TestFileMerge {

    /*
First way of thinking
1. data-a.txt  =>  data.txt
2. data-b.txt append => data.txt

The second way of thinking is that it is appropriate to merge in small quantities, but generally this is not the case
1. data-a.txt  => ByteArrayOutputStream
2. data-b.txt  => ByteArrayOutputStream
3. ByteArrayOutputStream byte[] => FileOutputStream

  */

    public static void main(String[] args) {
        String fileA = "E:" + File.separator + "File Test" + File.separator + "test" + File.separator + "data-a.txt";
        String fileB = "E:" + File.separator + "File Test" + File.separator + "test" + File.separator + "data-b.txt";
        String file = "E:" + File.separator + "File Test" + File.separator + "test" + File.separator + "data.txt";

        try (FileInputStream ain = new FileInputStream(fileA);
             FileInputStream bin = new FileInputStream(fileB);
             ByteArrayOutputStream bout = new ByteArrayOutputStream();
             FileOutputStream fout = new FileOutputStream(file);
        ) {
            byte[] buff = new byte[4];
            int len = -1;
            //ain  -> bout
            while ((len = ain.read(buff)) != -1) {
                bout.write(buff, 0, len);
            }

            //bin  -> bout
            while ((len = bin.read(buff)) != -1) {
                bout.write(buff, 0, len);
            }

            //bout -> fout
            byte[] joinData = bout.toByteArray();
            fout.write(joinData);
            fout.flush();
        } catch (IOException e) {

        }
    }
}

7. PrintWriter

Print streams are divided into byte print streams: PrintStream, character print stream: PrintWriter, which is more likely to be used in the future.
Look at their definitions:

public class PrintStream extends FilterOutputStream
    implements Appendable, Closeable
public class PrintWriter extends Writer

The design of print streams belongs to the decorative design mode: the core is still the function of a class, but it supports more functions for better operation.

        PrintWriter printWriter = new PrintWriter(new FileOutputStream(new File("E:"+
                File.separator+"File Test" + File.separator
                +"test"+File.separator+ "hello.txt")));
        printWriter.print(3);
        printWriter.print("lalallala");
        printWriter.print(3.16);
        //Get used to adding flush, or sometimes you won't see the output
        printWriter.flush();

8. System Output

Interview Points: What does System.out.println() mean?

System represents class name

out represents object, printStream

print is a method and a method of an out object

We can see that the definition of out in the System class is as follows: (visible as an object constant of a PrintStream class)

    public final static PrintStream out = null;

There are two constants for system output: out and err, and they represent objects of the PrintStream class.

  1. out outputs what you want the user to see
  2. Er output is content you don't want users to see

out and err are actually less useful in development and will be replaced by logs
Let's look at a simple code:

        PrintStream outputStream = System.out;
        outputStream.println("lalalla");

9. System input

System.in corresponds to the type InputStream, and this input stream refers to user input through the keyboard (user input).java itself does not
Direct user input processing, if you want to do this, must be done in java.io mode;

In practice, System.in is rarely used Because it also combines memory streams, which is cumbersome;

10. Two input streams

1.BufferedReader class

This is an input class used by Java more than a decade ago, so it is not explained much.

2.java.util.Scanner class ()

Print stream solves the defect of OutputStream class, BufferedReader solves the defect of InputStream class.Scanner's solution is
Defects in the BufferedReader class (replacing the BufferedReader class)
Scanner is a special program class for input stream processing, which can be used to process various data types conveniently, but also directly combine positive data
Then the expressions are processed, and in this class, the main concerns are the following:

  • First, let's look at how it is constructed:
    public Scanner(InputStream source) {
        this(new InputStreamReader(source), WHITESPACE_PATTERN);
    }
//It requires an InputStream as a parameter, and we know that System.in is the InputStream type.
  • Determine if there is data of the specified type: public boolean hasNextXxx()
        Scanner scanner = new Scanner(System.in);
        System.out.println( scanner.hasNextInt());
  • Gets the data of the specified type: public data type nextXxx()

  • Define the delimiter: public Scanner useDelimiter(Pattern pattern)

2.1 Basic usage of Scanner:
        Scanner scanner = new Scanner(System.in) ;
        System.out.println("Please enter data:") ;
        if (scanner.hasNext()) { // Has input, does not determine empty string
            System.out.println("The input is: "+scanner.next());
        }
        scanner.close() ;

Output:
Please enter data:
ijbhu
Input is: ijbhu

Process finished with exit code 0

2.2 Use Scanner to manipulate files: ()
public class Test {
    public static void main(String[] args) throws Exception{
        Scanner scanner = new Scanner(new FileInputStream("E://File Test Test print.txt));
        //c as the delimiter;
        scanner.useDelimiter("c");
        if(scanner.hasNext()) {
            System.out.println(scanner.next());
        }
        scanner.close();
    }
}

Output:
aaa
bbbbb

The data known in the file test print.txt is:
aaa
bbbbb
ccccc

11. Serialization

Object serialization refers to the transfer of an object stored in memory into a binary data stream or to the storage of it in text.But not
This means that objects of all classes can be serialized. Strictly speaking, class objects that need to be serialized often need to be transferred and used, and this class must implement
java.io.Serializable interface.But this interface has no method definition, it's just an identity.

If you want to serialize and deserialize object operations, there are two processing classes available in the java.io package: ObjectOutputStream,
ObjectInputStream

Topics: Java encoding Windows Database