Advanced Java programming knowledge - 10. IO flow

Posted by svenski on Sat, 22 Jan 2022 19:34:47 +0100

10.1 File class

  1. java. io. An object of the file class that represents a file or file directory

  2. Constructor creates a File instance:

    1. File(String filePath)
    2. File(String parent, File child)
    3. File(File parent, String child)
  3. Path separator:

    • windows and DOS systems use "\" by default

    • UNIX and URL s are represented by "/"

    • To solve this hidden danger, the File class provides a constant public static final String separator: the separator is dynamically provided according to the operating system

    • Note:

      • In Idea: the relative path in Junit unit test method is under the current module, and the relative path in main () method is under the current project
      • In Eclipse: the relative paths of the two methods are under the current project
  4. The File class involves the creation, deletion, renaming, modification time, File size and other methods of files (directories), and does not involve the operation of writing or reading File contents. To read or write the contents of a File, you must use an IO stream

  5. The subsequent File class will often be passed to the stream constructor as a parameter to indicate the "end point" of reading or writing

Common methods:

  1. String getAbsolutePath(): get absolute path
  2. String getPath(): get path
  3. String getName(): get name
  4. String getParent(): get the directory path of the upper level file, and return null if none
  5. long length(): get the file length (bytes), but not the directory length
  6. long lastModified(): gets the last modified time, in milliseconds
  7. boolean renameTo (File dest): rename this file to the specified file path
    • Requirement: this file exists on the hard disk, and dest file does not exist on the hard disk
  8. boolean exists(): judge whether it exists
  9. boolean isDirectory(): judge whether it is a file directory
  10. boolean isFile(): judge whether it is a file
  11. boolean canRead(): judge whether it is readable
  12. Boolean canwrite(): judge whether it is writable
  13. boolean isHidden(): judge whether it is hidden

The following methods apply to file directories:

  1. String [] list(): get the name array of all files or file directories in the specified directory
  2. File [] listfiles(): get the file array of all files or file directories in the specified directory

Create file (directory)

  1. boolean createNewFile(): creates a file. If the file already exists, it will not be created. false is returned

    File file = new File("create.txt");
            if(!file.exists()){
                file.createNewFile();
                System.out.println("Created successfully!");
            }else{
                file.delete();
                System.out.println("Delete succeeded!");
            }
    
  2. boolean mkdir(): creates a file directory. If it already exists or the upper directory does not exist, it will not be created. false is returned

  3. boolean mkdirs(): create a file directory. If the upper directory does not exist, create it together

Delete file (directory)

boolean delete(): deletes a file (directory). If there is content in the file directory, it will not be deleted and false will be returned

10.2 IO flow principle and classification

IO stream overview

  • IO: abbreviation of Input / Output, processing data transmission between devices, such as reading and writing files, network communication, etc

  • Stream: a standardized way of data input and output

Classification of flow

  • By operation data unit:
    • Byte stream (8bit) pictures and videos
    • Character stream (16bit) text
  • By data flow direction: input flow, output flow
  • Roles by flow: node flow, processing flow
(abstract base class)Byte streamCharacter stream
Input streamInputStreamReader
Output streamOutputStreamWriter

The child class names derived from these four classes are suffixed by their parent class names

IO stream system

Abstract base classNode stream (file stream)Buffer stream (one kind of processing stream)
InputStreamFileInputStream: int read(byte[] buffer)BufferedInputStream: int read(byte[] buffer)
OutputStreamFileOutputStream: write(byte[] buffer,0,len)BufferedOutputStream: write(byte[] buffer,0,len),flush()
ReaderFileReader: int read(char[] cbuf)BufferedReader: int read(char[] cbuf), String readLine()
WriterFileWriter: write(char[] cbuf,0,len)BufferedWriter: write(char[] cbuf,0,len),flush()

Standardization process of input and output

  1. Input process
    1. Create an object of File class to indicate the source of the read data (this File must exist)
    2. Create the corresponding input stream and pass the object of File class as a parameter into the stream constructor
    3. Specific read in process: create corresponding byte [] or char []
    4. Close stream resource
  2. Output process
    1. Create an object of File class, indicating the source of the read data (this File may not exist)
    2. Create the corresponding output stream and pass the object of File class as a parameter into the stream constructor
    3. Specific writing process: write (char[] / byte[] buffer, 0, len)
    4. Close stream resource

Note: try-catch0finally should be used to handle compile time exceptions in the program

FileReader

Read(): returns a character read in. If it reaches the end, it returns - 1

//1. Instantiate the object of File class to indicate the File to be operated on
File file = new File("hello.txt");
FileReader fr = null;
//2. Take the file as a formal parameter to provide a specific stream
try {
    fr = new FileReader(file);
    //3. Read in of data
    int data;
    while ((data = fr.read()) != -1) {
        System.out.println((char) data);
    }
}catch (IOException e){
    e.printStackTrace();
}finally {
    //4. Close operation of flow
    try {
       if(fr!=null)
        fr.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

explain:

  1. Read(): returns a character read in. If it reaches the end, it returns - 1
  2. Exception handling: in order to ensure that the stream resources can be closed, try catch finally is required
  3. The read file must exist, otherwise FileNotFoundException will be reported

Read (char [] cbuf): returns the number of characters read into the cbuf array each time. If it reaches the end of the file, it returns - 1

File file = new File("hello.txt");
        FileReader fr = null;
        try {
            fr = new FileReader(file);
            char[] cbuf = new char[5];
            int len;
            //Read (char[] cbuf): returns the number of characters read into the cbuf array each time. If it reaches the end of the file, it returns - 1
//			Mode 1
//            while((len=fr.read(cbuf))!=-1){
//                for (int i = 0; i <len ; i++) {
//                    System.out.print(cbuf[i]);
//                }
//            }
//			Mode II
            while((len=fr.read(cbuf))!=-1){
                String str = new String(cbuf, 0, len);
                System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(fr!=null)
                    fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

FileWriter

File file = new File("hello1.txt");
FileWriter fw = null;
try {
    fw = new FileWriter(file);
    fw.write("I have a dream!\n".toCharArray());
    fw.write("you need to have a dream");
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        if(fw!=null)
            fw.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

explain:

  1. Output operation: the corresponding File may not exist
    • If the File does not exist, it is automatically created during output
    • If File exists:
      • If the constructor used by the stream is FileWriter (file, false) or FileWriter (file), the original file content will be overwritten
      • If the constructor used by the stream is FileWriter (file, true), add it at the end of the original file content

practice:

File character stream copy text file

File srcFile = new File("hello.txt");
File tgtFile = new File("hello2.txt");
FileReader fr = null;
FileWriter fw = null;

try {
    fr = new FileReader(srcFile);
    fw = new FileWriter(tgtFile);

    char[] cbuf = new char[5];
    int len;
    while((len = fr.read(cbuf))!=-1){
        fw.write(cbuf,0,len);
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        if(fw!=null)
            fw.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        if(fr!=null)
            fr.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

The usage of FileInputStream and FileOutputStream is similar to that of FileReader and FileWriter

Conclusion:

  1. For text files (. txt,. java,. c,. cpp), use character streams FileReader and FileWriter for processing
  2. For non text files (. jpg,. mp3,. mp4,. avi,. doc,. ppt), use byte streams FileInputStream and FileOutputStream for processing
  3. If you only copy files, you can copy text files with byte streams (only transfer without printing), but you can't copy non text files with character streams

10.3 process flow

*Buffer stream

  1. Buffer stream:

    BufferedInputStream

    BufferedOutputStream

    BufferedReader

    BufferedWriter

  2. Function: improve the reading and writing speed of the stream

    Reason: a buffer is provided internally

  3. Processing a stream is "nested" on an existing stream

practice:

BufferedInputStream and BufferedOutputStream copy non text files

public void copyFile(String srcfile, String destfile) {
    File srcFile = new File(srcfile);
    File destFile = new File(destfile);
    FileInputStream fis = null;
    FileOutputStream fos = null;
    BufferedInputStream bis = null;
    BufferedOutputStream bos = null;

    try {
        fis = new FileInputStream(srcFile);
        fos = new FileOutputStream(destFile);

        bis = new BufferedInputStream(fis);
        bos = new BufferedOutputStream(fos);

        byte[] buffer = new byte[1024];

        int len;
        while ((len = bis.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (bis != null)
                bis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            if (bos != null)
                bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Requirement: first close the outer processing flow, and then close the inner node flow

Note: when the outer layer flow is closed, the inner layer flow will also be closed automatically, so the closing operation of the inner layer flow can be omitted

practice:

Buffer stream BufferedReader and BufferedWriter copy text files

public void copyFile(String srcfile, String desffile){
        BufferedReader br = null;
        BufferedWriter bw = null;

        try {
            br = new BufferedReader(new FileReader(new File(srcfile)));
            bw = new BufferedWriter(new FileWriter(new File(desffile)));
            char[] cbuf = new char[1024];

//            Method 1:
//            int len;
//            while((len=br.read(cbuf))!=-1){
//                bw.write(cbuf,0,len);
//            }

//            Method 2:
            String data;
            while((data=br.readLine())!=null){
//                bw.write(data+"\n");
                bw.write(data);
                bw.newLine();
            }
//            readLine() does not contain line breaks and needs to be added manually

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(br!=null){
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(bw!=null){
                    bw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }

*Conversion flow

  1. Conversion stream: belongs to character stream

    InputStreamReader: converts a byte input stream into a character input stream (decodes)

    OutputStreamWriter: converts a character output stream to a byte output stream

  2. Function: provide conversion (encoding) between byte stream and character stream

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-byaark4f-1642867698063) (C: \ users \ HP \ appdata \ roaming \ typora \ typora user images \ image-20220121110642231. PNG)]

public void test() throws IOException {
    FileInputStream fis = new FileInputStream("text.txt");
    InputStreamReader isr = new InputStreamReader(fis,"utf-8");
	//Parameter 2 indicates the character set, depending on the character set used by the file to be read and written
    char[] cbuf = new char[20];
    int len;
    while((len=isr.read(cbuf))!=-1){
        System.out.print(new String(cbuf,0,len));
    }
    isr.close();
}

Standard input / output stream

  1. System.in: standard input stream: input from keyboard by default

    System.out: standard output stream: output from console by default

  2. You can change the default device through the setIn() and setOut() methods of the System class

    • public static void setIn(InputStream in)
    • public static void setOut(PrintStream out)

Exercise: input the string from the keyboard, and constantly convert the read whole line of string into uppercase output until you exit the program when you enter e or exit

public static void main(String[] args)  {
    BufferedReader br = null;
    try {
        InputStream in = System.in;  //Byte stream
        InputStreamReader isr = new InputStreamReader(in);  //Convert byte stream to character stream with conversion stream
        br = new BufferedReader(isr);
        while (true) {
            System.out.println("Please enter a string:");
            String str = br.readLine();
            if(str == null || "e".equalsIgnoreCase(str) || "exit".equalsIgnoreCase(str))
                break;
            System.out.println(str.toUpperCase());
        }
        System.out.println("goodbye!");
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if(br!=null)
                br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Print stream

PrintStream and PrintWriter

  • Provides a series of overloaded print () and println () methods to output multiple data types
  • The output will not throw IOException
  • With automatic flush function
  • All characters printed by PrintStream are converted to bytes using the platform default character encoding
    • When you need to write characters instead of bytes, you should use the PrintWriter class
  • System.out returns the PrintSream class

Exercise: setting up a file output print stream

public void test2() throws IOException {
        FileOutputStream fos = new FileOutputStream("printStream.txt");
//        Create a printout stream and set it to auto refresh flush mode (the output buffer will be refreshed automatically when a newline character or byte '\ n' is written)
        PrintStream ps = new PrintStream(fos,true);
        System.setOut(ps);
        for(int i=0;i<256;i++){
            System.out.print((char)i);
            if(i%50==0) System.out.println();
        }
        ps.close();
    }

data stream

  1. DataInputStream and DataOutputStream
  2. Function: read and write basic data types or string variables

Note: the order of reading various types of data shall be consistent with the order of writing files

practice:

public void test3() throws IOException {
    DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
    dos.writeUTF("Lau Andy");
    dos.writeInt(23);
    dos.writeBoolean(true);
    dos.close();
}

public void test4() throws IOException {
    DataInputStream dos = new DataInputStream(new FileInputStream("data.txt"));
    String name = dos.readUTF();
    int age = dos.readInt();
    boolean male = dos.readBoolean();
    System.out.println("name = " + name);
    System.out.println("age = " + age);
    System.out.println("male = " + male);
    dos.close();
}

*Object flow

  1. ObjectInputStream and ObjectOutputStream
  2. Function: the processing stream used to store and read basic data type data or objects. You can write objects in Java to the data source (serialize) or restore objects from the data source (deserialize)

Objects must meet the following requirements before serialization

  1. The class should implement the Serializable interface
  2. The class must declare a global constant: public static final long serialVersionUID = xxxxxxl; (for version control)
  3. In addition to implementing the Serializable interface in the class, it is also necessary to ensure that all attributes within the class are Serializable (by default, the basic data type is Serializable)

Supplement: members decorated with static and transient cannot be serialized

Serialization process: save Java objects in memory to disk or transmit them over the network, which is implemented by ObjectOutputStream

public void test(){
    ObjectOutputStream oos = null;
    try {
        oos = new ObjectOutputStream(new FileOutputStream("obj.dat"));
        oos.writeObject(new String("I Love Beijing Tiananmen "));
        oos.flush(); //Refresh operation
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if(oos!=null)
                oos.close();
        }catch (IOException e) {
                e.printStackTrace();
            }
    }

}

Deserialization process: restore the object in disk file and network stream to a java object in memory, which needs to be implemented by ObjectInputStream

public void test1(){
    ObjectInputStream ois = null;
    try {
        ois = new ObjectInputStream(new FileInputStream("obj.dat"));
        Object obj = ois.readObject();
        String str = (String)obj;
        System.out.println(str);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } finally {
        if(ois!=null)
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
    }

}

Random access file stream

RandomAccessFile

  1. RandomAccessFile directly inherits from the Object class
  2. The DataInput and DataOutput interfaces are implemented, which means that this class can read and write
  3. As an output stream, if the written out file does not exist, it will be created automatically. If it does exist, the original content will be overwritten (overwritten from scratch by default)
  4. You can "insert" data by adjusting the pointer through seek

constructor

  • public RandomAccessFile(File file, String mode)
    
  • public RandomAccessFile(String name, String mode)
    

The mode parameter specifies the access mode of RandomAccessFile:

r: Open as read-only

rw: open for reading and writing

rwd: open for reading and writing; Synchronize file content updates

rws: open for reading and writing; Synchronize file content and metadata updates

public void test2() throws IOException{
    RandomAccessFile raf = new RandomAccessFile("hello.txt", "rw");
    raf.seek(3);//Adjust the pointer to the position marked 3
    raf.write("xyz".getBytes());
    raf.close();
}

Adjust the pointer through seek to "insert" data

    public void test3() throws IOException {
        int pos = 3;
        File file = new File("hello.txt");
        RandomAccessFile raf = new RandomAccessFile(file,"rw");
        raf.seek(pos);
        byte[] buffer = new byte[20];
        int len;
//        Save all data after pointer pos to StringBuilder
        StringBuilder str = new StringBuilder((int) file.length());
        while((len=raf.read(buffer))!=-1){
           str.append(new String(buffer,0,len));
        }
//        Call back the pointer and write xyz
        raf.seek(pos);
        raf.write("xyz".getBytes());
        raf.write(str.toString().getBytes());
        raf.close();
    }

There are more wonderful contents in my study notes
Java programming knowledge column

Topics: Java Eclipse intellij-idea