Comprehensive analysis of IO stream (including NIO description)

Keywords: Java Back-end

Use of File class

summary

  1. An object of the File class that represents a File or a File directory (commonly known as a folder)

  2. The File class is declared under the java.io package

  3. File class involves the creation, deletion, renaming, modification time, file size and other methods of files or file directories

    There is no operation to write or read the file content. If you need to read or write the file content, you must use IO stream to complete it

  4. Objects of subsequent File classes are often passed to the stream constructor as parameters to indicate the "end point" of reading or writing (which can be simply understood as: location)

explain

  1. How to create an instance of the File class

    Method 1: File(String filePath)

    Method 2: File(String parentPath, String childPath)

    Method 3: File(File parentFile, String childPath)

  2. route

    Relative path: the specified path compared to a certain path

    Absolute path: the path to the file or file directory including the drive letter

  3. Path separator: each level of directories in the path is separated by a path separator

    windows: \\
    unix: /
    
    • Java programs support cross platform operation, so the path separator should be used with caution.

    • To solve this problem, the File class provides a constant: public static final String separator. Separators are provided dynamically according to the operating system.

    • give an example:

      File file1 = new File("d:\\IO\\info.txt"); 
      File file2 = new File("d:" + File.separator + "IO" + File.separator + "info.txt"); 
      File file3 = new File("d:/IO");
      

case

package com.laoyang.test.day1;

import org.junit.Test;
import java.io.File;

/**
 * @ClassName Test
 * @Description:  File Use of classes
 * @Author Laoyang
 * @Date 2021/10/21 9:42
 */
public class FileTest {
    @Test
    public void testOne() {
        // Constructor 1
        File fileA = new File("hello.txt");  // Relative to the current module (Demo_15)

        /*
        * Each level of directories in the path is separated by a path separator.
        * The path separator is system dependent:
        > windows And DOS systems use "\ \" by default
        > UNIX And URL s are represented by "/"
        * Java The program supports cross platform operation, so the path separator should be used with caution.
        *To solve this problem, the File class provides a constant:
        > public static final String separator. Separators are provided dynamically according to the operating system.
        */
        File file1 = new File("d:\\info.txt");
        File file2 = new File("d:" + File.separator + "info.txt");

        File fileB = new File("D:\\Java\\project\\JavaDemo\\Demo_15\\hi.txt");   // Absolute path

        System.out.println(fileA);
        System.out.println(fileB);

        // Constructor 2
        File fileC = new File("D:\\Java\\project", "JavaDemo");
        System.out.println(fileC);

        // Constructor 3: find the corresponding file in the specified path
        File fileD = new File(fileC, "hi.txt");
        System.out.println(fileD);
    }
}

common method

Get function of File class

methodeffect
public String getAbsolutePath()Get absolute path
public String getPath()Get path
public String getName()Get name
public String getParent()Gets the directory path of the upper level file. If none, null is returned
public long length()Gets the length of the file (i.e. bytes). Cannot get the length of the directory
public long lastModified()Gets the last modification time, in milliseconds
public String[] list()Gets the name array of all files or file directories in the specified directory
public File[] listFiles()Gets the name array of all files or file directories in the specified directory

list() and listFiles() apply to file directories

Rename function of File class

methodeffect
public boolean renameTo(File dest)Rename the file to the specified file path

Simple understanding of function: rename the file stored in the hard disk and put it into the specified file directory

Requirement: to return true (successful execution), fileA must exist in the hard disk, and fileB must not exist in the hard disk

Judgment function of File class

methodeffect
public boolean isDirectory()Determine whether it is a file directory
public boolean isFile()Determine whether it is a file
public boolean exists()Judge whether it exists
public boolean canRead()Judge whether it is readable
public boolean canWrite()Determine whether it is writable
public boolean isHidden()Determine whether to hide

Creation function of File class (creating corresponding files or File directories in the hard disk)

methodeffect
public boolean createNewFile()Create a file. If the file exists, it will not be created and false will be returned
public boolean mkdir()Create a file directory. If this file directory exists, it will not be created.
If the upper directory of this file directory does not exist, it will not be created.
public boolean mkdirs()Create a file directory. If the upper file directory does not exist, create it together

Note: if you create a file or the file directory does not have a write letter path, it is under the project path by default.

Delete function of File class

methodeffect
public boolean delete()Delete files or folders

matters needing attention:

  1. Deletions in Java do not go to the recycle bin.
  2. To delete a file directory, the file directory cannot contain files or file directories. If files or file directories are included, they cannot be deleted

case

package com.laoyang.test.day1;

import org.junit.Test;
import java.io.File;
import java.io.IOException;

/**
 * @ClassName FileCommonMethod
 * @Description:  File Common methods of class
 * @Author Laoyang
 * @Date 2021/10/21 10:27
 */
public class FileCommonMethod {
    /**
      File Class
      public String getAbsolutePath(): Get absolute path
      public String getPath() : Get path
      public String getName() : Get name
      public String getParent(): Gets the directory path of the upper level file. If none, null is returned
      public long length() : Gets the length of the file (i.e. bytes). Cannot get the length of the directory.
      public long lastModified() : Gets the last modification time, in milliseconds

      The following two methods apply to file directories
      public String[] list() : Gets the name array of all files or file directories in the specified directory
      public File[] listFiles() : Gets the name array of all files or file directories in the specified directory
     */
    @Test
    public void testOne() {
        File fileA = new File("hello.txt");
        File fileB = new File("F:\\IO\\hi.txt");

        // Get the absolute path: D:\Java \ project \ JavaDemo\Demo_15\hello.txt
        System.out.println(fileA.getAbsolutePath());
        // Get path: hello.txt
        System.out.println(fileA.getPath());
        // Get name: hello.txt
        System.out.println(fileA.getName());
        /*
         Gets the directory path of the upper level file. If not, null: null is returned
         (It is obtained according to the path in the parameter. For example, the relative path here has only the file name (hello.txt) and no upper level directory information, so it returns null whether the file is created or not)
         */
        System.out.println(fileA.getParent());
        /*
         Gets the length of the file (that is, the number of bytes). Cannot get the length of the directory: 0
         (Return 0 before creating the file, and return the corresponding length according to the number of bytes of the content after creating the file)
         */
        System.out.println(fileA.length());
        /*
         Gets the last modification time, in milliseconds: 0
         (Return 0 before creating a file. After creating a file, return the number of milliseconds according to the time of the last modification (you can use time type conversion to standard time format for viewing))
         */
        System.out.println(fileA.lastModified());

        System.out.println("---------------------------------------");

        // Get absolute path: F:\IO\hi.txt
        System.out.println(fileB.getAbsolutePath());
        // Get path: F:\IO\hi.txt
        System.out.println(fileB.getPath());
        // Get name: hi.txt
        System.out.println(fileB.getName());
        /*
         Get the upper level file directory path. If none, null: F:\IO is returned
         (Because the absolute path is used here, there is the file directory information of the upper layer in the parameter path (F:\IO), so the directory information of the upper layer can be obtained regardless of whether the corresponding file is found in the end)
         */
        System.out.println(fileB.getParent());
        /*
         Gets the length of the file (that is, the number of bytes). Cannot get the length of the directory: 0
         (Return 0 before creating the file, and return the corresponding length according to the number of bytes of the content after creating the file)
         */
        System.out.println(fileB.length());
        /*
         Gets the last modification time, in milliseconds: 0
         (Return 0 before creating a file. After creating a file, return the number of milliseconds according to the time of the last modification (you can use time type conversion to standard time format for viewing))
         */
        System.out.println(fileB.lastModified());
    }

    /**
      The following two methods apply to file directories
      public String[] list() : Gets the name array of all files or file directories in the specified directory
      public File[] listFiles() : Gets the File array of all files or File directories in the specified directory
     */
    @Test
    public void testOneB() {
        File fileA = new File("D:\\Java\\project\\JavaDemo");
        /*
        When using these two methods, the parameter directory must actually exist, or an error will be reported: NullPointerException
         */
        String[] list = fileA.list();
        for (String s : list) {
            System.out.println(s);  // Gets the names of all files or file directories in the specified directory
        }

        File[] files = fileA.listFiles();
        for (File file : files) {
            System.out.println(file);   // Get all files or file directories in the specified directory
        }
    }

    /**
     File Rename function of class
      public boolean renameTo(File dest):Rename the file to the specified file path
     (The function of this method is simple to understand: rename the file stored in the hard disk and put it into the specified file directory)
     Requirement: to return true (successful execution), fileA must exist in the hard disk, and fileB must not exist in the hard disk
     */
    @Test
    public void testTwo() {
        File fileA = new File("hello.txt");
        File fileB = new File("F:\\IO\\hi.txt");
        boolean b = fileB.renameTo(fileA);
        System.out.println(b);
    }

    /**
      File Class judgment function
      public boolean isDirectory(): Determine whether it is a file directory
      public boolean isFile() : Determine whether it is a file
      public boolean exists() : Judge whether it exists
      public boolean canRead() : Judge whether it is readable
      public boolean canWrite() : Determine whether it is writable
      public boolean isHidden() : Determine whether to hide
     */
    @Test
    public void testThree() {
        /*
        File test
         */
        File fileA = new File("hello.txt");
        System.out.println(fileA.isDirectory()); // Is it a file directory
        System.out.println(fileA.isFile());      //Is it a file
        System.out.println(fileA.exists());      // Does it exist
        System.out.println(fileA.canRead());     // Is it readable
        System.out.println(fileA.canWrite());    // Is it writable
        System.out.println(fileA.isHidden());    // Hide

        System.out.println("------------------------------------");

        /*
        File directory test. Here I write two file directories, one exists and the other does not exist. You can test them all
         */
        File fileB = new File("F:\\IO");    // Directory exists
//        fileB = new File("F:\ioi");        //  directory does not exist
        System.out.println(fileB.isDirectory()); // Is it a file directory
        System.out.println(fileB.isFile());      //Is it a file
        System.out.println(fileB.exists());      // Does it exist
        System.out.println(fileB.canRead());     // Is it readable
        System.out.println(fileB.canWrite());    // Is it writable
        System.out.println(fileB.isHidden());    // Hide
    }

    /**
      File Class creation function (create the corresponding file or file directory in the hard disk)
      public boolean createNewFile() : Create a file. If the file exists, it will not be created and false will be returned
      public boolean mkdir() : Create a file directory. If this file directory exists, it will not be created. If the upper directory of this file directory does not exist, it will not be created.
      public boolean mkdirs() : Create a file directory. If the upper file directory does not exist, create it together
     Note: if you create a file or the file directory does not have a write letter path, it is under the project path by default.
     */
    @Test
    public void testFour() throws IOException {
        // File creation
        File fileA = new File("hi.txt");
        // If the file does not exist, it is created in. Otherwise, it is not created
        if (!fileA.exists()) {
            boolean newFile = fileA.createNewFile();
            if (newFile) {
                System.out.println("Created successfully!");
            }
        }
    }

    @Test
    public void testFourB() {
        // Creation of file directory
        File fileA = new File("F:\\IO\\day1\\java1");   // Because the upper level directory (day1) does not exist, it will cause creation failure
        boolean mkdir = fileA.mkdir();
        if (mkdir) {
            System.out.println("Created successfully A!");
        }

        File fileB = new File("F:\\IO\\day1\\java2");
        boolean mkdirs = fileB.mkdirs();
        if (mkdirs) {
            System.out.println("Created successfully B!");
        }
    }

    /**
      File Class deletion function
      public boolean delete(): Delete files or folders
     Precautions for deletion:
     1. Java Deletions in do not go to the recycle bin.
     2. To delete a file directory, the file directory cannot contain files or file directories. If files or file directories are included, they cannot be deleted
     */
    @Test
    public void testFive() {
        // Because there is also a java2 folder in it, it cannot be deleted here
        File fileA = new File("F:\\IO\\day1");
        if (fileA.exists()) {
            boolean delete = fileA.delete();
            if (delete)
                System.out.println("Delete succeeded!");
        } else {
            System.out.println("File does not exist!");
        }
    }
}

practice

Judge whether there is a file with the suffix. jpg in the specified directory. If so, output the file name

package com.laoyang.test.day2;

import org.junit.Test;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;

/**
 * @ClassName FindJPGFileTest
 * @Description:  Judge whether there is a file with the suffix. jpg in the specified directory. If so, output the file name
 * @Author Laoyang
 * @Date 2021/10/21 17:10
 */
public class FindJPGFileTest {
   /**
    * Method 1: use the list() method
    */
   @Test
   public void test1(){
      File srcFile = new File("F:\\IO\\day1\\java1");
      String[] fileNames = srcFile.list();    // Get all file names in the current directory
      for(String fileName : fileNames){
         if(fileName.endsWith(".jpg")){    // Judge according to the currently obtained file name
            System.out.println(fileName);
         }
      }
   }

   /**
    * Method 2: use listFiles() method
    * Ps: In fact, it is similar to the first method. It also needs to use the endsWith() method in the String class for judgment
    */
   @Test
   public void test2(){
      File srcFile = new File("F:\\IO\\day1\\java1");
      
      File[] listFiles = srcFile.listFiles();
      for(File file : listFiles){
         if(file.getName().endsWith(".jpg")){
            System.out.println(file.getAbsolutePath());
         }
      }
   }

   /*
    * Mode 3:
    * File Class provides two file filter methods
    * public String[] list(FilenameFilter filter)
    * public File[] listFiles(FileFilter filter)
    */
   @Test
   public void test3() {
      File srcFile = new File("F:\\IO\\day1\\java1");

      // FilenameFilter
      File[] subFiles = srcFile.listFiles(new FilenameFilter() {
         @Override
         public boolean accept(File dir, String name) {
            return name.endsWith(".jpg");
         }
      });

      for (File file : subFiles) {
         System.out.println(file.getAbsolutePath());
      }

      // FileFilter
      File file = new File("F:\\IO\\day1\\java1");
      File[] files = file.listFiles(new FileFilter() {
         @Override
         public boolean accept(File pathname) {
            return pathname.getName().endsWith(".jpg");
         }
      });

      for (File fileA : files) {
         System.out.println(fileA.getAbsolutePath());
      }
   }
}

Here are three implementation methods, which you can test by yourself

Traverse all file names in the specified directory, including files in the sub file directory

Extension 1: and calculate the space occupied by the specified directory

Extension 2: delete the specified file directory and all files under it

package com.laoyang.test.day2;

import org.junit.Test;
import java.io.File;

/**
 * @ClassName ListFilesTest
 * @Description:  Traverse all file names in the specified directory, including files in the sub file directory.
 * @Author Laoyang
 * @Date 2021/10/21 17:10
 */
public class ListFilesTest {
   /**
    * Method 1: recursive acquisition
    */
   public static void main(String[] args) {
      // Recursion: file directories
      // 1. Create directory object
      File dir = new File("F:\\IO");

      // 2. Print sub files of the directory
      printSubFile(dir);
   }

   public static void printSubFile(File dir) {
      // Print sub files of the directory
      File[] subfiles = dir.listFiles();

      for (File f : subfiles) {
         // Determine whether it is a file directory
         if (f.isDirectory()) {
            // If it is a file directory, use the recursive method to judge again until there is no file directory
            printSubFile(f);
         } else {
            // If it is not a file directory, the absolute path of the file is printed directly
            System.out.println(f.getAbsolutePath());
         }
      }
   }

   /**
    * Mode 2: Circular implementation
    * List the subordinate contents of the file directory. If only one level is listed
    * Using String[] list() of File class is relatively simple
    * > If you only print the folder information of the next layer, you can use String[] list
    */
   @Test
   public void testOne() {
      // 1. Create directory object
      File dir = new File("F:\\IO\\day1");
      // 2. Print the sub file name and folder name of the directory
      listSubFiles(dir);
   }

   public void listSubFiles(File file) {
      if (file.isDirectory()) {
         String[] all = file.list();
         for (String s : all) {
            System.out.println(s);
         }
      } else {
         System.out.println(file + "It's a file!");
      }
   }

   /**
    * Mode III
    */
   @Test
   public void testThree() {
      // 1. Create directory object
      File dir = new File("F:\\IO");
      // 2. Print sub files of the directory
      listAllSubFiles(dir);
   }

   /**
    List the subordinates of the file directory. If its subordinates are still directories, then list the subordinates of the subordinates, and so on
    It is recommended to use File[] listFiles() of File class
    */
   public void listAllSubFiles(File file) {
      if (file.isFile()) {
         System.out.println(file);
      } else {
         File[] all = file.listFiles();
         /*
          If all[i] is a file, print directly
          If all[i] is a directory, then get its next level
          Note: don't be confused here
          1. This recursion is what is called in the loop, so the condition for the execution of the recursive method is: no end is ended.
          2. For the recursive method parameters in the loop, f is used except for file for the first time, so you can directly find the next layer and continue to find it
          Suppose: if it is found that it is not a file during the first execution, then loop through all files in the file directory (all file information under D:\IO)
               In the second execution, if it is found that it is not a file, obtain all information (files and folders) in the subdirectory (all file information under D:\IO\day1)
               In the third execution, if it is found to be a file, after printing the file information, execute the loop not completed in else again, traverse the next file / folder and judge again
               ......And so on until there is no next layer or no file
         One last point: when a directory is found from beginning to end, it will start in the second directory
         > For example, D:\IO\day1 and D:\IO\day1. At this time, there are two folders under the IO directory. At this time, day1 will be traversed first, and then day2 will be traversed,
         > Therefore, there is no problem that you can no longer traverse other folders under the home directory (IO) after entering the depths of a subdirectory
          */
         for (File f : all) {
            System.out.println("------------" + f);
            listAllSubFiles(f);  // Recursive call: calling yourself is called recursion
         }
      }
   }
}

The above also adopts three implementation methods

  • Method 1 is implemented by recursion
  • Method 2 can only obtain the information of the child, not the child of the child, such as A/B/C. If you obtain it from A, you can only obtain the file information of B, not C
  • The third method also uses recursion, but it is different from the first one. You can understand it in combination with comments

extend

package com.laoyang.test.day2;

import org.junit.Test;
import java.io.File;

/**
 * @ClassName ListFilesTest
 * @Description:  Traverse all file names in the specified directory, including files in the sub file directory.
 * @Author Laoyang
 * @Date 2021/10/21 17:10
 */
public class ListFilesTest {
   /**
    * Extension 1: find the size of the space where the specified directory is located (find the total size of any directory)
    */
   @Test
   public void testFour() {
      File file = new File("F:\\IO");
      long directorySize = getDirectorySize(file);
      System.out.println(directorySize);
   }

   /**
    Find the total size of any directory
    */
   public long getDirectorySize(File file) {
      // If file is a file, return file.length() directly
      // file is a directory. Adding up all the sizes of its next level is its total size
      long size = 0;
      if (file.isFile()) {
         size += file.length();
      } else {
         File[] all = file.listFiles();// Gets the next level of the file
         // Cumulative size of all[i]
         for (File f : all) {
            /*
             f The size of the; Don't be confused about this, because size plus the return value of the getDirectorySize() method
             Moreover, this size always exists in the loop, so it will not be affected by the external size = 0
             */
            size += getDirectorySize(f);
         }
      }
      return size;
   }

   /**
    * Extension 2: delete the specified directory
    */
   @Test
   public void testFive() {
      File file = new File("F:\\IO");
      deleteDirectory(file);
   }

   public void deleteDirectory(File file) {
      /*
       If file is a file, delete it directly
       If file is a directory, first kill its next level, and then delete yourself
       */
      if (file.isDirectory()) {
         File[] all = file.listFiles();
         /*
          The next level of file is deleted circularly; f represents each subordinate of the file
          Logic: first delete the files under the subdirectory, then delete the subdirectory, and finally delete the current directory
          */
         for (File f : all) {
            deleteDirectory(f);
         }
      }
      // Delete yourself
      boolean delete = file.delete();
      if (delete) {
		  System.out.println("Delete succeeded!");
	  }
   }
}

IO stream principle and stream classification

Java IO stream principle

  • I/O is the abbreviation of Input/Output. I/O technology is a very practical technology for processing data transmission between devices. Such as reading / writing files, network communication, etc.
  • In Java programs, the input / output operation of data is carried out in the form of "stream".
  • Various "stream" classes and interfaces are provided under the java.io package to obtain different kinds of data and input or output data through standard methods.

Java IO principle

  • input: read external data (data from disk, optical disc and other storage devices) into the program (memory).
  • Output: output program (memory) data to disk, optical disc and other storage devices.

Classification of flow

  1. Operation data unit: byte stream, character stream
  2. Data flow direction: input flow and output flow
  3. Roles of flow: node flow and processing flow

Java's IO stream involves more than 40 classes, which are actually very regular and derived from the following four abstract base classes.

Abstract base classByte streamCharacter stream
Input streamInputStreamReader
Output streamOutputStreamWriter

InputStream method description

  • int read(): reads the next byte of data from the input stream. Returns an int byte value in the range 0 to 255. If no bytes are available because the end of the stream has been reached, the value - 1 is returned.
  • int read(byte[] b): read up to b.length bytes of data into a byte array from this input stream. If no bytes are available because the end of the stream has been reached, the value - 1 is returned. Otherwise, the number of bytes actually read is returned as an integer.
  • int read(byte[] b, int off,int len): read up to len data bytes in the input stream into the byte array. An attempt was made to read len bytes, but the bytes read may also be less than this value. Returns the number of bytes actually read as an integer. If no bytes are available because the stream is at the end of the file, the value - 1 is returned.
  • public void close() throws IOException: close this input stream and release all system resources associated with the stream.

Reader method description

  • int read(): reads a single character. Characters read as integers, ranging from 0 to 65535 (0x00-0xffff) (2-byte Unicode code). If the end of the stream has been reached, it returns - 1
  • int read(char[] cbuf): reads characters into an array. Returns - 1 if the end of the stream has been reached. Otherwise, it returns the number of characters read this time.
  • int read(char[] cbuf,int off,int len): read characters into a part of the array. Store in the array cbuf, start from off, and read len characters at most. Returns - 1 if the end of the stream has been reached. Otherwise, it returns the number of characters read this time.
  • public void close() throws IOException: close this input stream and release all system resources associated with the stream.

OutputStream method description

  • void write(int b) OutputStream: writes the specified bytes to this output stream. The general convention of write is to write a byte to the output stream. The bytes to be written are the eight low bits of parameter B. The 24 high bits of B will be ignored. That is, write in the range of 0 ~ 255.
  • void write(byte[] b): writes b.length bytes from the specified byte array to this output stream. The general convention of write(b) is that it should have exactly the same effect as calling write(b, 0, b.length).
  • void write(byte[] b,int off,int len): write len bytes from offset off in the specified byte array to this output stream.
  • public void flush()throws IOException: flushes this output stream and forces all buffered output bytes to be written out. Calling this method indicates that these bytes should be written to their expected destination immediately.
  • public void close() throws IOException: close this output stream and release all system resources associated with the stream.

Writer method description

  • void write(int c): write a single character. The character to be written is contained in the 16 low bits of the given integer value, and the 16 high bits are ignored. That is, write the Unicode code between 0 and 65535.
  • void write(char[] cbuf): writes a character array.
  • void write(char[] cbuf,int off,int len): write to a part of the character array. Starting from off, write len characters
  • void write(String str): writes a string.
  • void write(String str,int off,int len): writes a part of a string.
  • void flush(): flushes the buffers of the stream and writes them to the expected destination immediately.
  • public void close() throws IOException: close this output stream and release all system resources associated with the stream.

Because the character stream directly takes the character as the operation unit, the Writer can replace the character array with a String, that is, take the String object as the parameter.

explain

  1. The input stream and output stream methods are basically universal, and the routines used are similar. You can find it in the following cases
  2. Here is a more official explanation, so it seems that some explanations seem vague or official. Later, there is a more grounded explanation for everyone to understand

IO stream system

Understanding of node flow and processing flow

Node flow: read and write data directly from the data source or destination

Processing flow: it is not directly connected to the data source or destination, but "connected" on the existing flow (node flow or processing flow), so as to provide more powerful reading and writing functions for the program through data processing.

Use of node stream (also known as file stream)

Stream object

Node flowByte streamCharacter stream
Input streamFileInputStreamFileReader
Output streamFileOutputStreamFileWriter

Byte stream read() overload method

int read()
int read(byte[] b)
int read(byte[] b, int off, int len)

Character stream read() overload method

int read()
int read(char [] c)
int read(char [] c, int off, int len)

Note: the file IO resource opened in the program does not belong to the resource in memory, and the garbage collection mechanism cannot recycle the resource, so it is necessary to explicitly close the file IO resource.

Attention

  • When defining the file path, note that "/" or "\" can be used.
  • When writing a file, if the constructor FileOutputStream(file) is used, a file with the same name in the directory will be overwritten.
  • If the constructor FileOutputStream(file, true) is used, the file with the same name in the directory will not be overwritten, and content will be appended at the end of the file content.
  • When reading a file, you must ensure that the file already exists, otherwise an exception will be reported.
  • Byte stream operation bytes, such as:. mp3,. avi,. rmvb, mp4,. jpg,. doc,. ppt
  • Character stream can only operate on ordinary text files. The most common text files:. txt,. java,. c,. cpp and other language source code. In particular, note that. Doc, Excel and PPT are not text files.

The difference between unit test and main() method in relative path

  1. If the unit test method is used for testing, the default is to find the corresponding file under the current module (only the corresponding file will be found in the current module / project)

  2. If the main() method is used for testing, the corresponding file under the current project will be found by default (if the parent-child project is used, the corresponding file will be found in the parent project by default)

    If you use Eclipse, the relative path will find the corresponding file under the current project by default, whether in the unit test or in the main() method

case

package com.laoyang.test.day3;

import org.junit.Test;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * @ClassName IOTest
 * @Description:  IO Use of stream
 * @Author Laoyang
 * @Date 2021/10/23 10:32
 */
public class IOTest {
    /**
     * Unit test print results
     * D:\Java\Project \ JavaDemo\Demo_15\hello.txt
     * D:\Java\Project \ JavaDemo\Demo_15\Demo_15\hello.txt
     *
     * main Method print results
     * D:\Java\Project \ JavaDemo\hello.txt
     * D:\Java\Project \ JavaDemo\Demo_15\hello.txt
     */
    public static void main(String[] args) {
        File file = new File("hello.txt");  // Compared with the current project (JavaDemo)
        System.out.println(file.getAbsoluteFile());

        File fileB = new File("Demo_15\\hello.txt");
        System.out.println(fileB.getAbsolutePath());
    }
}

Here we only demonstrate the of mian() method. If you are interested, you can create a unit test method for comparison

Basic steps of node flow

  1. Instantiate the object of File class to indicate the File to be operated on
  2. Provide specific flow
  3. Data input and output operation
  4. Closure of flow

Character stream case

Input stream - FileReader

Description point

  1. read() method: returns a character read. If it reaches the end of the file, it returns - 1
  2. Exception handling: to ensure that resources can be closed, try catch finally is used
  3. The read file must exist, or FileNotFoundException will be reported
package com.laoyang.test.day3;

import org.junit.Test;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * @ClassName IOTest
 * @Description:  IO Use of stream
 * @Author Laoyang
 * @Date 2021/10/23 10:32
 */
public class IOTest {
    /**
     * Use of node flow
     * FileReader
     * FileWriter
     * Add Demo_15 (current module), read the contents of the hello.txt file into the program and output it to the console
     */
    @Test
    public void testOne() {
        FileReader reader = null;
        try {
            // 1. Instantiate the object of File class to indicate the File to be operated
            File file = new File("hello.txt");  // Compared with the current Module (Demo_15)
            // 2. Provide specific flow
            reader = new FileReader(file);

            /*
             3. Data reading
             read(): Returns a character read. If it reaches the end of the file, it returns - 1
             */
            // Mode 1
//            int read = reader.read();
//            while (read != -1) {
//                System.out.print((char) read);
//                read = reader.read();
//            }

            // In mode 2, there is no difference in performance for the modification of mode 1
            int read;
            while ((read = reader.read()) != -1) {
                System.out.print((char) read);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // try{}catch() {} here can be written inside or outside if
            try {
                /*
                 The purpose of this judgment is to prevent exceptions from occurring when the reader has not been instantiated
                 If the reader is not instantiated and then close s directly, an error will be reported (for example, you want to swim in a river without water)
                 */
                if (reader != null) {
                    // 4. Close data (be sure to add!!!)
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Operation upgrade of read() method: use the overloaded method of read()

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

    The characters in the corresponding file are read in several times according to the length set by the cbuf array. For example, if it is set to 5 here, five characters will be read from the file each time

  • read(char[] cbuf, int off, int len): cbuf (get the array size of characters), off (where to start storing), len (get the length of characters each time)

    Read the characters in the file according to the length set by len. Even if the array length is 100 and len is set to 5, only 5 characters will be read from the file and stored in the cbuf array at most each time; off indicates where the read character is stored in the array. For example, if I don't want to store it from scratch, I can set it to a subscript value other than 0
    This overload method is not recommended in development!!!

package com.laoyang.test.day3;

import org.junit.Test;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * @ClassName IOTest
 * @Description:  IO Use of stream
 * @Author Laoyang
 * @Date 2021/10/23 10:32
 */
public class IOTest {
    /**
     * Operation upgrade of read() method: use the overloaded method of read()
     */
    @Test
    public void testTwo() {
        FileReader reader = null;
        try {
            // 1. Instantiation of file class
            File file = new File("hello.txt");

            // 2. Instantiation of FileReader stream
            reader = new FileReader(file);

            /*
             3. Read operation
             read(char[] cbuf): Returns the number of characters in the cbuf array read each time. If it reaches the end of the file, it returns - 1
             > The characters in the corresponding file are read in several times according to the length set by the cbuf array. For example, if it is set to 5 here, five characters will be read from the file each time
             read(char[] cbuf, int off, int len): cbuf(Get the array size of characters), off (where to start storing), len (get the length of characters each time)
             > Read the characters in the file according to the length set by len. Even if the array length is 100 and len is set to 5, at most 5 characters will be read from the file and stored in the cbuf array
             > off Indicates where the read character is stored in the array. For example, if I don't want to store it from scratch, I can set it to a subscript value other than 0
             > This overload method is not recommended in development!!!
             */
            char[] cbuf = new char[5];
            int read = reader.read(cbuf);
            while (read != -1) {
                // Mode 1
                // Wrong writing
//                for (int i = 0; i < cbuf.length; i++) {
//                    System.out.print(cbuf[i]);
//                }

                // Correct writing
//                for (int i = 0; i < read; i++) {
//                    System.out.print(cbuf[i]);
//                }

                // Mode II
                // Wrong writing
//                String str = new String(cbuf);
//                System.out.println(str);

                // Correct writing
                String str = new String(cbuf, 0, read);
                System.out.print(str);

                read = reader.read(cbuf);
            }

            // 4. Output operation, because this is just a demonstration of the use of the read() overload method, there is no write read operation

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 5. Closure of resources
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

Output stream - FileWriter

Description point

  1. For output operation, the corresponding File may not exist and no exception will occur.

  2. If the File in the hard disk corresponding to File does not exist, it will be automatically created during output.
    If the File in the hard disk corresponding to File exists:
    If the constructor used by the stream is: FileWriter(file, false) / FileWriter(file): the original file will be overwritten
    If the constructor used by the stream is: FileWriter(file, true): the original file will not be overwritten, but added at the end of the content of the original file

package com.laoyang.test.day3;

import org.junit.Test;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * @ClassName IOTest
 * @Description:  IO Use of stream
 * @Author Laoyang
 * @Date 2021/10/23 10:32
 */
public class IOTest {
    /**
     * Write data from memory to a file on the hard disk
     */
    @Test
    public void testThree() {
        FileWriter writer = null;
        try {
            // 1. Provide an object of File class, indicating the File to be written to
            File file = new File("helloA.txt");

            /*
             2. Provides a FileWriter object for writing data
             The second parameter indicates adding or overwriting. true indicates adding to the back of the file, and false indicates overwriting the file
             */
            writer = new FileWriter(file, true);

            /*
             3. Write operation
              write(String str): Case: writer.write("Java!");
              write(char cbuf[]): Case: writer.write("Java!". toCharArray());
             */
            writer.write("java is the best language in the world!\n");
            writer.write("none of them!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 4. Closing of flow resources
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Combination of input stream and output stream

package com.laoyang.test.day3;

import org.junit.Test;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * @ClassName IOTest
 * @Description:  IO Use of stream
 * @Author Laoyang
 * @Date 2021/10/23 10:32
 */
public class IOTest {
    /**
     * Combination of input stream and output stream
     */
    @Test
    public void testFour() {
        FileReader reader = null;
        FileWriter writer = null;
        try {
            // 1. Create an object of File class to indicate the files to be read and written
            File read = new File("hello.txt");
            File write = new File("helloA.txt");

            // 2. Create objects for input and output streams
            reader = new FileReader(read);
            writer = new FileWriter(write);

            // 3. Input and output operation
            char[] cbuf = new char[5];
            // Record the number of characters read into the cbuf array each time
            int len = reader.read(cbuf);
            while (len != -1) {
                // Write len characters at a time
                writer.write(cbuf, 0, len);
                len = reader.read(cbuf);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 4. Close the flow resource. At this time, the closing sequence is not specified
            // Mode 1
//            try {
//                if (writer != null) {
//                    writer.close();
//                }
//            } catch (IOException e) {
//                e.printStackTrace();
//            } finally {
//                try {
//                    if (reader != null) {
//                        reader.close();
//                    }
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
            // Mode 2: Recommended
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

The process is similar

The character stream cannot handle the test of picture files

package com.laoyang.test.day3;

import org.junit.Test;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * @ClassName FilePictureTest
 * @Description:  The character stream cannot handle the test of picture files
 * @Author Laoyang
 * @Date 2021/10/23 16:08
 */
public class FilePictureTest {
    /**
     Note: character stream cannot be used to process byte data such as pictures. Character stream can only process character data
     */
    @Test
    public void testOne() {
        FileReader reader = null;
        FileWriter writer = null;
        try {
            // 1. Create a File object to indicate the read and write files
            File fileA = new File("2.jpg");
            File fileB = new File("3.jpg");

            // 2. Instantiate the objects of input stream and output stream
            reader = new FileReader(fileA);
            writer = new FileWriter(fileB);

            // 3. Perform read and write operations
            char[] cbuf = new char[5];
            int read = reader.read(cbuf);
            while (read != -1) {
                // It can be written successfully, but the written file cannot be used normally, because only character files can be processed, and pictures belong to byte files
                writer.write(cbuf, 0, read);
                read = reader.read(cbuf);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally{
            // 4. Close flow operation
            try {
                if (writer != null)
                    writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (reader != null)
                    reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Byte stream case

Description point

  1. For text files (. txt,. java,. c,. cpp, etc.), use character stream processing

    Source document - read in memory (garbled code may appear if read in memory, for example: testOne())

    Source document - copy (during the copy process, it will not be read in memory, but will be directly provided to us for viewing after the copy, so there will be no garbled code, such as testFour())

  2. For non text files (. jpg,. mp3,. mp4,. avi,. ppt, etc.), use byte stream processing

Input stream - FileInputStream

package com.laoyang.test.day3;

import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @ClassName FileByteStreamTest
 * @Description:  Use of byte stream (use of FileInputStream and FileOutputStream)
 * @Author Laoyang
 * @Date 2021/10/23 16:21
 */
public class FileByteStreamTest {
    /**
     * Byte stream - use of FileInputStream
     * Using byte stream FileInputStream to process text files may cause garbled code
     */
    @Test
    public void testOne() {
        FileInputStream inputStream = null;
        try {
            // 1. Create a File object to indicate the File to be read
            File file = new File("hello.txt");

            // 2. Instantiate byte stream object
            inputStream = new FileInputStream(file);

            // 3. Read operation
            byte[] buffer = new byte[5];
            int read = inputStream.read(buffer);
            while (read != -1) {
                // A Chinese character occupies three bytes
                String str = new String(buffer, 0, read);
                System.out.print(str);	// Garbled code
                read = inputStream.read(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 4. Close flow operation
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Combination of input stream and output stream (FileOutputStream)

package com.laoyang.test.day3;

import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @ClassName FileByteStreamTest
 * @Description:  Use of byte stream (use of FileInputStream and FileOutputStream)
 * @Author Laoyang
 * @Date 2021/10/23 16:21
 */
public class FileByteStreamTest {
    /**
     * Copy the picture
     */
    @Test
    public void testTwo() {
        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;

        try {
            // Indicates the file to copy
            File fileA = new File("2.jpg");
            File fileB = new File("3.jpg");

            // Instantiate byte object
            inputStream = new FileInputStream(fileA);
            outputStream = new FileOutputStream(fileB);

            // Replication process
            byte[] buffer = new byte[5];
            int read = inputStream.read(buffer);
            while (read != -1) {
                outputStream.write(buffer, 0, read);
                read = inputStream.read(buffer);
            }
            System.out.println("Copy succeeded!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // Close flow
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

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

Copy of files under the specified path - Video & document

package com.laoyang.test.day3;

import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @ClassName FileByteStreamTest
 * @Description:  Use of byte stream (use of FileInputStream and FileOutputStream)
 * @Author Laoyang
 * @Date 2021/10/23 16:21
 */
public class FileByteStreamTest {
    /**
     * Copy of files under the specified path - VIDEO
     */
    @Test
    public void testThree() {
        long currentTimeMillis = System.currentTimeMillis();

        String strPath = "C:\\Users\\Laoyang\\Videos\\B station\\other\\The day of the dull King-english\\The day of the dull King.mp4";
        String destPath = "C:\\Users\\Laoyang\\Videos\\B station\\other\\The day of the dull King-english\\A day of staying in the king.mp4";
        copyFile(strPath, destPath);

        long currentTimeMillis1 = System.currentTimeMillis();
        System.out.println("Total time:" + (currentTimeMillis1 - currentTimeMillis));
    }

    /**
     * Copy of files under the specified path - Document
     */
    @Test
    public void testFour() {
        long currentTimeMillis = System.currentTimeMillis();

        String strPath = "hello.txt";
        String destPath = "helloA.txt";
        copyFile(strPath, destPath);

        long currentTimeMillis1 = System.currentTimeMillis();
        System.out.println("Total time:" + (currentTimeMillis1 - currentTimeMillis));
    }

    /**
     * General method
     */
    public void copyFile(String strPath, String destPath) {
        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;

        try {
            // Indicates the file to copy
            File fileA = new File(strPath);
            File fileB = new File(destPath);

            // Instantiate byte object
            inputStream = new FileInputStream(fileA);
            outputStream = new FileOutputStream(fileB);

            // Replication process
            byte[] buffer = new byte[1024];
            int read = inputStream.read(buffer);
            while (read != -1) {
                outputStream.write(buffer, 0, read);
                read = inputStream.read(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // Close flow
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Because the logical codes are almost the same, we directly use the general method to reduce the amount of code for convenience

Processing stream 1: use of cache stream

explain

  1. In order to improve the speed of data reading and writing, the Java API provides stream classes with buffering function. When using these stream classes, an internal buffer array will be created. By default, a buffer of 8192 bytes (8Kb) is used.

    BufferedInputStream part of the source code

    public class BufferedInputStream extends FilterInputStream {
    	// Buffer, first store the read data in the buffer of 8192 size, and then obtain the data in it at one time
        private static int DEFAULT_BUFFER_SIZE = 8192;
    }
    
    For example: now there is a 10 L A water cup and a 5 L The water cup is required to be filled with 100 L It can be seen that the last one to fill up must be 10 L Water cup
    
  2. Processing flow is to "socket" based on the existing flow

  3. When reading data, the data is read into the buffer by block, and subsequent read operations directly access the buffer

  4. When using BufferedInputStream to read a byte file, BufferedInputStream will read 8192 bytes (8Kb) from the file at one time and store them in the buffer. It will not read the next 8192 byte array from the file until the buffer is full.

  5. When writing bytes to the stream, they will not be directly written to the file. They will be written to the buffer first. BufferedOutputStream will not write the data in the buffer to the file at one time until the buffer is full. Use the method flush() to force all the contents of the buffer to be written to the output stream

  6. The order in which the flow is closed is opposite to the order in which it is opened. Just turn off the outermost flow, and turning off the outermost flow will turn off the inner node flow accordingly

  7. Use of the flush() method: manually write the contents of the buffer to the file

  8. If it is the close() method of a stream object with buffer, it will not only close the stream, but also refresh the buffer before closing the stream. After closing, it can't be written out

Stream object

Buffer streamByte streamCharacter stream
Input streamBufferedInputStreamBufferedReader
Output streamBufferedOutputStreamBufferedWriter

case

  • Buffer stream

    BufferedInputStream: process byte input
    BufferedOutputStream: process byte output
    BufferedReader: handles character input
    BufferedWriter handles character output

  • Function: improve the read and write speed of the stream

    Reason for improving read and write speed: a buffer is provided internally

Use of BufferedInputStream and BufferedOutputStream

package com.laoyang.test.day3;

import org.junit.Test;
import java.io.*;

/**
 * @ClassName BufferedTest
 * @Description:  One of the processing streams: the use of buffer streams
 * @Author Laoyang
 * @Date 2021/10/23 17:04
 */
public class BufferedTest {
    /**
     * Using BufferedInputStream and BufferedOutputStream to copy non text files
     */
    @Test
    public void testOne() {
        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;

        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            // 1. Create a File object to indicate the File to be copied
            File fileA = new File("2.jpg");
            File fileB = new File("4.jpg");

            // 2. Instantiate flow object
            // 2.1: instantiate node flow objects
            inputStream = new FileInputStream(fileA);
            outputStream = new FileOutputStream(fileB);

            // 2.2: instantiate buffer stream object
            bis = new BufferedInputStream(inputStream);
            bos = new BufferedOutputStream(outputStream);

            // 3. Copy details, read and write
            byte[] buffer = new byte[10];
            int read = bis.read(buffer);
            while (read != -1) {
                bos.write(buffer, 0, read);
                read = bis.read(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            /*
             4. Resource shutdown
             Requirements: close the outer layer first and close the inner layer later
             Note: while closing the outer laminar flow, the inner laminar flow will also be closed automatically. We can omit the closing of the inner laminar flow
             */
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

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

            // The closing of inner flow can be omitted
//            inputStream.close();
//            outputStream.close();
        }
    }

    /**
     * Method of file replication - VIDEO
     * Compare the read and write speeds of buffer stream and byte stream
     */
    @Test
    public void testTwo() {
        long currentTimeMillis = System.currentTimeMillis();

        String srcPath = "C:\\Users\\Laoyang\\Videos\\B station\\other\\The day of the dull King-english\\The day of the dull King.mp4";
        String destPath = "C:\\Users\\Laoyang\\Videos\\B station\\other\\The day of the dull King-english\\A day in a hippo.mp4";

        copyFileWithBuffered(srcPath, destPath);

        long currentTimeMillis1 = System.currentTimeMillis();

        System.out.println("Total time:" + (currentTimeMillis1 - currentTimeMillis));
    }

    /**
     * General method
     */
    public void copyFileWithBuffered(String srcPath, String destPath) {
        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;

        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            // 1. Create a File object to indicate the File to be copied
            File fileA = new File(srcPath);
            File fileB = new File(destPath);

            // 2. Instantiate flow object
            // 2.1: instantiate node flow objects
            inputStream = new FileInputStream(fileA);
            outputStream = new FileOutputStream(fileB);

            // 2.2: instantiate buffer stream object
            bis = new BufferedInputStream(inputStream);
            bos = new BufferedOutputStream(outputStream);

            // 3. Copy details, read and write
            byte[] buffer = new byte[1024];
            int read = bis.read(buffer);
            while (read != -1) {
                bos.write(buffer, 0, read);
                read = bis.read(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 4. Resource shutdown
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

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

Use of BufferedReader and BufferedWriter

package com.laoyang.test.day3;

import org.junit.Test;
import java.io.*;

/**
 * @ClassName BufferedTest
 * @Description:  One of the processing streams: the use of buffer streams
 * @Author Laoyang
 * @Date 2021/10/23 17:04
 */
public class BufferedTest {
    /**
     * Use BufferedReader and BufferedWriter to copy text files
     */
    @Test
    public void testThree() {
        BufferedReader reader = null;
        BufferedWriter writer = null;
        try {
            // 1. Create a File object to indicate the File to be copied
            File fileA = new File("hello.txt");
            File fileB = new File("hi.txt");

            // 2. Instantiate the buffer stream object (here, for convenience, we directly use the anonymous object to pass parameters)
            reader = new BufferedReader(new FileReader(fileA));
            writer = new BufferedWriter(new FileWriter(fileB));

            // 3. Read write (copy) operation
            // Method 1: use char [], read() to read characters of the specified size each time
//            char[] cbuf = new char[5];
//            int read = reader.read(cbuf);
//            while (read != -1) {
//                writer.write(cbuf, 0, read);
//                read = reader.read(cbuf);
//            }

            // Method 2: use String, readLine() to read one line of characters at a time
            String data = reader.readLine();
            while (data != null) {
                // data does not contain newline characters
//                writer.write(data);   //  nowrap 

                // Line feed method 1: \ n
//                writer.write(data + "\n");

                //Line feed mode 2: newLine()
                writer.write(data);

                writer.newLine();
                data = reader.readLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // Close flow
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

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

Little practice

Exercise one

Node streams: FileInputStream, FileOutputStream and buffer streams: BufferedInputStream and BufferedOutputStream are used to copy text files / pictures / video files respectively. And compare their efficiency in data replication

package com.laoyang.test.day4;

import org.junit.Test;
import java.io.*;

/**
 * @ClassName CopyExerciseTest
 * @Description:  Exercise 1: use node streams: FileInputStream, FileOutputStream and buffer streams: BufferedInputStream and BufferedOutputStream to copy text files / pictures / video files respectively. And compare their efficiency in data replication
 * @Author Laoyang
 * @Date 2021/10/24 15:58
 */
public class CopyExerciseTest {
    /**
     * Node flow
     */
    @Test
    public void testFile() {
        long start = System.currentTimeMillis();

        // Copy file (1 ms, file too small)
        nodeFlow("hello.txt", "new file.txt");

        // Copy picture (13-14 MS)
//        nodeFlow("2.jpg", "new picture. jpg");

        // Copy video (83-86 MS)
//        nodeFlow("C:\Users\Laoyang\Videos\B station \ \ others \ \ day of dull King - English \ \ day of dull king. mp4", "new video. mp4");

        long finish = System.currentTimeMillis();

        System.out.println("Total time:" + (finish - start));
    }

    /**
     * FileInputStream,FileOutputStream method
     */
    public void nodeFlow(String srcPath, String destPath) {
        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;
        try {
            inputStream = new FileInputStream(srcPath);
            outputStream = new FileOutputStream(destPath);
            byte[] buffer = new byte[1024];
            int read = inputStream.read(buffer);
            while (read != -1) {
                outputStream.write(buffer, 0, read);
                read = inputStream.read(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * Buffer stream
     */
    @Test
    public void testBuffered() {
        long start = System.currentTimeMillis();

        // Copy file (0 ms, file too small)
        bufferStream("hello.txt", "new file.txt");

        // Copy picture (3-4 MS)
//        bufferStream("2.jpg", "new picture. jpg");

        // Copy video (18-19 MS)
//        bufferStream("C:\Users\Laoyang\Videos\B station \ \ others \ \ day of dull King - English \ \ day of dull king. mp4", "new video. mp4");

        long finish = System.currentTimeMillis();

        System.out.println("Total time:" + (finish - start));
    }

    public void bufferStream(String srcPath, String descPath) {
        BufferedInputStream input = null;
        BufferedOutputStream output = null;

        try {
            input = new BufferedInputStream(new FileInputStream(srcPath));
            output = new BufferedOutputStream(new FileOutputStream(descPath));

            byte[] buffer = new byte[1024];
            int read = input.read(buffer);
            while (read != -1) {
                output.write(buffer, 0, read);
                read = input.read(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (output != null) {
                try {
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Exercise 2

Realize image encryption and decryption.

package com.laoyang.test.day4;

import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @ClassName PicTest
 * @Description:  Exercise 2: implement image encryption and decryption.
 * @Author Laoyang
 * @Date 2021/10/24 15:13
 */
public class PicTest {
    /**
     * Encryption operation
     */
    @Test
    public void testOne() {
        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;

        try {
            File fileA = new File("2.jpg");
            File fileB = new File("222.jpg");

            inputStream = new FileInputStream(fileA);
            outputStream = new FileOutputStream(fileB);

            byte[] buffer = new byte[10];
            int read = inputStream.read(buffer);
            while (read != -1) {
                // Modify the character array
                // Wrong writing: at this time, only the local variables in the loop are changed
    //            for (byte b : buffer) {
    //                b = (byte) (b ^ 5);
    //            }
                // Correct writing
                for (int i = 0; i < read; i++) {
                    buffer[i] = (byte) (buffer[i] ^ 5);     // Encryption operation
                }

                outputStream.write(buffer, 0, read);
                read = inputStream.read(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * Decryption operation
     */
    @Test
    public void testTwo() {
        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;

        try {
            File fileA = new File("222.jpg");   // File to decrypt
            File fileB = new File("333.jpg");   // Decrypted file

            inputStream = new FileInputStream(fileA);
            outputStream = new FileOutputStream(fileB);

            byte[] buffer = new byte[10];
            int read = inputStream.read(buffer);
            while (read != -1) {
                // Modify the character array
                // Wrong writing: at this time, only the local variables in the loop are changed
                //            for (byte b : buffer) {
                //                b = (byte) (b ^ 5);
                //            }
                // Correct writing
                for (int i = 0; i < read; i++) {
                    buffer[i] = (byte) (buffer[i] ^ 5);     // Encryption operation
                }

                outputStream.write(buffer, 0, read);
                read = inputStream.read(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Exercise three

Gets the number of times characters appear on the text and writes the data to the file.

Idea:

  • Traverse each character of the text

  • The number of occurrences of the character exists in the Map

    Map<Character,Integer> map = new HashMap<Character,Integer>();

    map.put('a',18);

    map.put('You ', 2);

  • Write the data in the map to the file

package com.laoyang.test.day4;

import org.junit.Test;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @ClassName PicTest
 * @Description:  Exercise 3: get the number of characters on the text and write the data to the file.
 * @Author Laoyang
 * @Date 2021/10/24 15:13
 */
public class WordCount {
    /*
    Note: if unit testing is used, the file relative path is the current module
         If the main() test is used, the relative path of the file is the current project
     */
    @Test
    public void testWordCount() {
        FileReader fr = null;
        BufferedWriter bw = null;
        try {
            //1. Create a Map collection, Character: the wrapper class of Character
            Map<Character, Integer> map = new HashMap<Character, Integer>();

            //2. Traverse each character and put the number of occurrences of each character into the map. Here, you can directly use the File path without creating a File object in advance
            fr = new FileReader("hello.txt");
            // When using the read() null parameter method, the default is to search one character by one
            int c = 0;
            while ((c = fr.read()) != -1) {
                //int restore char
                char ch = (char) c;
                // Determine whether char appears for the first time in the map
                if (map.get(ch) == null) {
                    map.put(ch, 1);
                } else {
                    // map.get(ch) + 1: indicates the number of occurrences of the character + 1. When the key value is the same, this operation is used as a modification operation
                    map.put(ch, map.get(ch) + 1);
                }
            }

            //3. Save the data in the map to the file wordcount.txt
            //3.1 create Writer
            bw = new BufferedWriter(new FileWriter("wordcount.txt"));

            //3.2 traverse the map and write the data
            Set<Map.Entry<Character, Integer>> entrySet = map.entrySet();
            for (Map.Entry<Character, Integer> entry : entrySet) {
                switch (entry.getKey()) {
                    case ' ':
                        bw.write("Space=" + entry.getValue());
                        break;
                    case '\t'://\t represents the tab key character
                        bw.write("tab key=" + entry.getValue());
                        break;
                    case '\r'://
                        bw.write("enter=" + entry.getValue());
                        break;
                    case '\n'://
                        bw.write("Line feed=" + entry.getValue());
                        break;
                    default:
                        bw.write(entry.getKey() + "=" + entry.getValue());
                        break;
                }
                //Line feed
                bw.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4. Shut off
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bw != null) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Processing flow 2: use of conversion flow

explain

  1. Conversion stream (identify character stream or byte stream according to the last keyword, and Reader and Writer represent character stream): it belongs to character stream

  2. Function: provide conversion between byte stream and character stream

  3. When the data in the byte stream is all characters, the operation of converting to character stream is more efficient.

  4. Many times, we use transform stream to deal with the problem of file scrambling. Realize the functions of encoding and decoding.

    Decoding: byte, byte array to character array, string

    Encoding: character array, string to byte, byte array

Stream object

Conversion flowCharacter stream
Input streamInputStreamReader
Output streamOutputStreamWriter

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

InputStreamReader description

  • The input stream of bytes is converted into the input stream of characters according to the specified character set.

  • Need to "socket" with InputStream.

  • constructor

    public InputStreamReader(InputStream in)
    public InputSreamReader(InputStream in,String charsetName) 
    
    For example: Reader isr = new InputStreamReader(System.in,"gbk");
    > gbk Represents the character set
    

OutputStreamWriter description

  • The output stream of characters is converted into the output stream of bytes according to the specified character set.

  • Need to "socket" with OutputStream.

  • constructor

    public OutputStreamWriter(OutputStream out)
    public OutputSreamWriter(OutputStream out,String charsetName)
    

case

explain

public InputSreamReader(InputStream in,String charsetName) 
public OutputSreamWriter(OutputStream out,String charsetName)
  • charsetName indicates the character set. Which character set to use depends on the character set used when saving the specified file (hello.txt here).

  • If the character code set is different from the character code when saving, it may lead to garbled code. For example, using utf-8 when saving and gbk when reading will lead to garbled code.

  • If charsetName is not set, the current compiler character set format is used by default. If charsetName is set, the set character set format is used.

Use of InputStreamReader

package com.laoyang.test.day5;

import org.junit.Test;
import java.io.*;

/**
 * @ClassName InputStreamReaderTest
 * @Description:  Processing flow 2: use of conversion flow
 * @Author Laoyang
 * @Date 2021/10/24 16:25
 */
public class InputStreamReaderTest {
    /**
     * At this time, try catch finally is still used when handling exceptions
     * InputStreamReader Use of: realize the conversion from byte input stream to character input stream
     */
    @Test
    public void testOne() {
        FileInputStream inputStream = null;
        InputStreamReader streamReader = null;
        try {
            inputStream = new FileInputStream("hello.txt");
            /*
             The second parameter represents the character set: which character set to use depends on the character set used when saving the specified file (hello.txt here)
             If the character code set is different from the character code when saving, it may lead to garbled code. For example, using utf-8 when saving and gbk when reading will lead to garbled code
             If parameter 2 is not set, the default character set format of the current compiler is used. If it is set, the set character set format is used
             */
//            streamReader = new InputStreamReader(inputStream, "GBK");
            streamReader = new InputStreamReader(inputStream, "UTF-8");

            char[] cbuf = new char[10];
            int read = streamReader.read(cbuf);
            while (read != -1) {
                String str = new String(cbuf, 0, read);
                System.out.print(str);
                read = streamReader.read(cbuf);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (streamReader != null) {
                try {
                    streamReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Use InputStreamReader and OutputStreamWriter together

explain:
If the character set of the copied file is modified to GBK, there will be garbled code when it is opened in the IDEA, because I now set the IDEA to UTF-8, but it can be displayed normally when it is opened with software such as notepad and notepad + +, because they can automatically use the corresponding character set for display

package com.laoyang.test.day5;

import org.junit.Test;
import java.io.*;

/**
 * @ClassName InputStreamReaderTest
 * @Description:  Processing flow 2: use of conversion flow
 * @Author Laoyang
 * @Date 2021/10/24 16:25
 */
public class InputStreamReaderTest {
    /**
     * Use InputStreamReader and OutputStreamWriter together
     */
    @Test
    public void testTwo() {
        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;

        InputStreamReader streamReader = null;
        OutputStreamWriter streamWriter = null;

        try {
            // 1. Create a File object to indicate the File to be operated
            File fileA = new File("hello.txt");
            File fileB = new File("hello_gbk.txt");

            // 2. Instantiation flow
            inputStream = new FileInputStream(fileA);
            outputStream = new FileOutputStream(fileB);

            streamReader = new InputStreamReader(inputStream, "UTF-8");
            streamWriter = new OutputStreamWriter(outputStream, "GBK");

            // 3. Reading and writing process
            char[] cbuf = new char[10];
            int read = streamReader.read(cbuf);
            while (read != -1) {
                streamWriter.write(cbuf, 0, read);
                read = streamReader.read(cbuf);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 4. Close the flow
            if (streamWriter != null) {
                try {
                    streamWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (streamReader != null) {
                try {
                    streamReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Extensions: character encoding

  • Origin of coding table

    Computers can only recognize binary data, which originated from electrical signals in the early days. In order to facilitate the application of the computer, it can recognize the characters of various countries. The words of each country are expressed in numbers and correspond one by one to form a table. This is the coding table.

  • Common encoding table (character set)

    ASCII: American standard information interchange code.

    It can be represented by 7 bits of a byte.

    ISO8859-1: Latin code table. European code table

    Represented by 8 bits of a byte.

    GB2312: Chinese coding table of China. Up to two bytes encode all characters

    GBK: China's Chinese coding table has been upgraded to integrate more Chinese characters and symbols. Up to two byte encoding

    Unicode: international standard code, which integrates all characters currently used by human beings. Assign a unique character code to each character. All text is represented by two bytes.

    UTF-8: variable length encoding method. 1-4 bytes can be used to represent a character.

  • Before the emergence of Unicode, all character sets were bound with specific encoding schemes (i.e. character set ≈ encoding mode), which directly bound the characters to the final byte stream.

  • GBK and other double byte encoding methods, the highest bit is 1 or 0 to represent two bytes and one byte.

  • Unicode is not perfect. Here are three problems

    First: we already know that only one byte is enough for English letters

    Second: how can I distinguish Unicode from ASCII? How does the computer know that two bytes represent one symbol instead of two symbols respectively?

    Third: if the encoding method is the same as GBK and other double byte encoding methods, and the highest bit is 1 or 0 to represent two bytes and one byte, there are many fewer values, which can not be used to represent characters, not enough to represent all characters.

    Unicode could not be popularized for a long time until the emergence of the Internet.

  • Many UTF (UCS Transfer Format) standards for data transfer to have emerged. As the name suggests, UTF-8 transfers data 8 bits at a time, while UTF-16 transfers data 16 bits at a time. This is a code designed for transmission and makes the code borderless, so that the characters of all cultures in the world can be displayed.

  • Unicode only defines a huge and universal character set, and specifies a unique number for each character. The specific byte stream stored depends on the character encoding scheme. The recommended Unicode encodings are UTF-8 and UTF-16.

Coding application of transform stream

  • You can store characters in a specified encoding format
  • Text data can be interpreted according to the specified coding format
  • The action of specifying the encoding table is completed by the constructor

Use of other processing streams

Use of standard input and output streams

explain

  1. System.in and System.out represent the input and output devices of the system standard respectively

  2. Default input device: keyboard

    The output device is: display

  3. The type of System.in is InputStream

  4. The type of System.out is PrintStream, which is a subclass of OutputStream and a subclass of FilterOutputStream

  5. Redirection: 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)

case

Input the string from the keyboard, and it is required to convert the read whole line of string into uppercase output. Then continue the input operation until you exit the program when you enter "e" or "exit".

Method 1: use the Scanner implementation and call next() to return a string
Method 2: use System.in to implement, and convert System.in to the readLine() method of BufferedReader

package com.laoyang.test.day6;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @ClassName OtherStreamTest
 * @Description:  Use of standard input and output streams
 * @Author Laoyang
 * @Date 2021/10/24 17:21
 */
public class StandardInputAndOutputTest {
    public static void main(String[] args) {
        BufferedReader bufferedReader = null;
        try {
            InputStreamReader streamReader = new InputStreamReader(System.in);
            bufferedReader = new BufferedReader(streamReader);
            while (true) {
                System.out.print("Please enter a string:");
                String data = bufferedReader.readLine();
                if ("e".equalsIgnoreCase(data) || "exit".equalsIgnoreCase(data)) {
                    System.out.println("The program is over!|");
                    break;
                }
                String upperCase = data.toUpperCase();	// Convert the currently obtained string to uppercase for printing
                System.out.println(upperCase);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

practice

Create a program named MyInput.java: it contains the method to read int, double, float, boolean, short, byte and String values from the keyboard

package com.laoyang.test.day6;

import java.io.*;

/**
 * @ClassName OtherStreamTest
 * @Description:  Exercise: create a program named MyInput.java: it contains methods to read int, double, float, boolean, short, byte and String values from the keyboard
 * @Author Laoyang
 * @Date 2021/10/24 17:21
 */
public class MyInput {
    /**
     * Read the value entered from the keyboard
     */
    public static String readString() {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        // Declare and initialize string
        String string = "";

        // Get string from keyboard
        try {
            string = br.readLine();

        } catch (IOException ex) {
            System.out.println(ex);
        }

        // Returns the string obtained from the keyboard
        return string;
    }

    /**
     * Read an int value from the keyboard
     */
    public static int readInt() {
        return Integer.parseInt(readString());
    }

    /**
     * Read a double value from the keyboard
     */
    public static double readDouble() {
        return Double.parseDouble(readString());
    }

    /**
     * Read a byte value from the keyboard
     */
    public static double readByte() {
        return Byte.parseByte(readString());
    }

    /**
     * Read a short value from the keyboard
     */
    public static double readShort() {
        return Short.parseShort(readString());
    }

    /**
     * Read a long value from the keyboard
     */
    public static double readLong() {
        return Long.parseLong(readString());
    }

    /**
     * Read a float value from the keyboard
     */
    public static double readFloat() {
        return Float.parseFloat(readString());
    }
}

Note: Although this class can receive different types of values input from the keyboard, if the receiving type used is inconsistent with the input data type, an error will still be reported!!!

Use of print streams

explain

  1. The data format of the basic data type is converted to string output
  2. Print streams: PrintStream and PrintWriter
  3. Provides a series of overloaded print() and println() methods for output of multiple data types
  4. The output of PrintStream and PrintWriter will not throw IOException
  5. PrintStream and PrintWriter have automatic flush function
  6. All characters printed by PrintStream are converted to bytes using the platform's default character encoding. When you need to write characters instead of bytes, you should use the PrintWriter class.
  7. System.out returns an instance of PrintStream

Stream object

Print streamCharacter streamByte stream
Input streamnothingnothing
Output streamPrintStreamPrintWriter

Note: print stream only has output stream, no input stream!!!

case

Use of PrintStream
package com.laoyang.test.day6;

import org.junit.Test;
import java.io.*;

/**
 * @ClassName PrintStreamTest
 * @Description:  Use of print streams
 * @Author Laoyang
 * @Date 2021/10/24 17:51
 */
public class PrintStreamTest {
    /**
     * Print stream: use of PrintStream
     */
    @Test
    public void testOne() {
        PrintStream ps = null;
        try {
            // It is possible that the file does not exist, but the directory where the file is stored must exist!
            FileOutputStream fos = new FileOutputStream(new File("F:\\IO\\day1\\hello.txt"));

            // Create a printout stream and set it to automatic refresh mode (the output buffer will be refreshed when writing newline character or byte '\ n'). If you don't want automatic refresh, change it to false or don't write
            ps = new PrintStream(fos, true);
            // Change the standard output stream (console output) to a file
            if (ps != null) {
                System.setOut(ps);
            }

            // Output ASCII characters
            for (int i = 0; i <= 255; i++) {
                System.out.print((char) i);
                // Every 50 data rows
                if (i % 50 == 0) {
                    System.out.println();   // Line feed
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (ps != null) {
                ps.close();
            }
        }
    }
}

Set System.out.print(); The values in are stored in the specified file

Use of PrintWriter
package com.laoyang.test.day6;

import org.junit.Test;
import java.io.*;

/**
 * @ClassName PrintStreamTest
 * @Description:  Use of print streams
 * @Author Laoyang
 * @Date 2021/10/24 17:51
 */
public class PrintStreamTest {
    /**
     * Print stream: use of PrintWriter
     */
    @Test
    public void testTwo() {
        PrintWriter printWriter = null;

        try {
            FileOutputStream streamWriter = new FileOutputStream(new File("F:\\IO\\day1\\hello.txt"));

            printWriter = new PrintWriter(streamWriter, true);

            // Stores ASCII characters in the specified file
            for (int i = 0; i <= 255; i++) {
                printWriter.print((char) i);
                // Every 50 data rows
                if (i % 50 == 0) {
                   printWriter.println();   // Line feed
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (printWriter != null)
                printWriter.close();
        }
    }
}

Set printWriter.print(); The values in are stored in the specified file

Use of data streams

explain

  1. In order to easily manipulate the basic data types of Java language and String data, you can use data flow.

  2. Data flow has two classes: (function: to read or write variables or strings of basic data types)

    DataInputStream and DataOutputStream

    "Socket" on the streams of subclasses InputStream and OutputStream respectively

  3. Methods in DataInputStream

    boolean readBoolean()byte readByte()char readChar()
    float readFloat()double readDouble()short readShort()
    long readLong()int readInt()String readUTF()
    void readFully(byte[] b)
  4. Method in DataOutputStream: change the read of the above method to the corresponding write.

case

package com.laoyang.test.day6;

import org.junit.Test;
import java.io.*;

/**
 * @ClassName DataFlowTest
 * @Description:  Processing flow 5: use of data flow
 * @Author Laoyang
 * @Date 2021/10/25 14:58
 */
public class DataFlowTest {
    /**
     * The process of writing, and the use of DataOutputStream
     */
    @Test
    public void testOne(){
        DataOutputStream dos = null;
        try {
            dos = new DataOutputStream(new FileOutputStream("data.txt"));

            // flush(): refresh operation to write data in memory to a file
            dos.writeUTF("Xiaobai");
            dos.flush();
            dos.writeInt(18);
            dos.flush();
            dos.writeBoolean(true);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (dos != null) {
                try {
                    dos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * Reading: use of DataInputStream
     * Exercise: read the basic data type variables and strings stored in the file into memory and save them in variables
     * Note: the order of reading different types of data should be consistent with the order when writing the file
     */
    @Test
    public void testTwo() {
        DataInputStream dis = null;
        try {
            // 1. Instantiate the object of the flow (because the processes are similar, the previous operations are combined here)
            dis = new DataInputStream(new FileInputStream("data.txt"));
            /*
             2. Read operation, specified here
             Regulation: read according to the order of writing, otherwise java.io.EOFException will be reported
             */
            String name = dis.readUTF();
            int age = dis.readInt();
            boolean isMale = dis.readBoolean();
            System.out.println(name);
            System.out.println(age);
            System.out.println(isMale);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 3. Close the flow
            if (dis != null) {
                try {
                    dis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

After writing data in the specified file, you cannot directly open it for viewing, because it will cause garbled code; if you want to view the correct data, you can use DataInputStream to read it

Use of object streams

explain

  1. Object streams: ObjectInputStream and ojbectoutputstream
  2. Function: a processing stream used to store and read basic data type data or objects. Its strength is that it can write objects in Java to the data source and restore objects from the data source.
  3. Serialization: a mechanism for holding basic type data or objects with the ObjectOutputStream class
  4. Deserialization: a mechanism for reading basic type data or objects with the ObjectInputStream class
  5. ObjectOutputStream and ObjectInputStream cannot serialize static and transient decorated member variables

object serialization

  1. The object serialization mechanism allows the java object in memory to be converted into a platform independent binary stream, which allows the binary stream to be permanently saved on disk or transmitted to another network node through the network; when other programs obtain the binary stream, they can be restored to the original java object

  2. The advantage of serialization is that it can convert any object that implements the Serializable interface into byte data, so that it can be restored during saving and transmission

  3. Serialization is a mechanism that must be implemented for both parameters and return values of RMI (Remote Method Invoke) process, and RMI is the basis of Java EE. Therefore, serialization mechanism is the basis of Java EE platform

  4. If an object needs to support serialization mechanism, the class to which the object belongs and its properties must be serializable. In order for a class to be serializable, the class must implement one of the following two interfaces. Otherwise, a NotSerializableException is thrown

    Serializable and Externalizable

  5. All classes that implement the Serializable interface have a static variable representing the serialization version identifier: private static final long serialVersionUID;

    • serialVersionUID is used to indicate compatibility between different versions of a class. In short, its purpose is to use serialized objects for version control, and whether each version is compatible when deserialized.

    • If the class does not show the definition of this static constant, its value is automatically generated by the Java runtime environment according to the internal details of the class. If the instance variable of the class is modified, the serialVersionUID may change. Therefore, explicit declaration is recommended.

    For example, the current class does not define the serialVersionUID constant, and the attributes are only name and age temporarily. At this time, OjbectOutputSteam is used to write;

    Then add a new attribute id and its get/set methods to the current class. At this time, an error will be reported when using ObjectInputStream to read;

    Because the versions are different at this time, suppose that the first version is 1, and then after adding the id attribute, the version becomes 2. Since version 1 has been upgraded to 2, an error will be reported when looking for the data of version 1 at this time.

  6. In short, the serialization mechanism of Java verifies the version consistency by judging the serialVersionUID of the class at run time. During deserialization, the JVM will compare the serialVersionUID in the transmitted byte stream with the serialVersionUID of the corresponding local entity class. If they are the same, they are considered to be consistent and can be deserialized. Otherwise, an exception of inconsistent serialization version will occur. (InvalidCastException)

Serialize objects using object streams

To serialize an object
  1. Create ObjectOutputStream stream object

  2. Call the writeobject (object) method of the ObjectOutputStream object to output the serializable object

    Note: write once and operate flush() once

  3. Close flow

To deserialize an object
  1. Create ObjectInputStream stream stream object

  2. Call the readObject() method to read the object in the stream

    Note: if different types of objects are added, the read object types must be in the same order as the written object types. For example, the first time you write a String object and the second time you write a User object, you must read the String object first and then the User object, otherwise an error will be reported!

  3. Close flow

be careful

If the attribute of a class is not a basic data type or String type, but another reference type, the reference type must be serializable, otherwise the class with this type cannot be serialized

See "using custom classes to implement serialization and deserialization" for details

case

Serialization process: save java objects in memory to disk or transfer them over the network

Deserialization process: restore the object in the disk file to a java object in memory

package com.laoyang.test.day6;

import org.junit.Test;
import java.io.*;

/**
 * @ClassName ObjectStreamTest
 * @Description:  Processing flow 6: use of object flow
 * @Author Laoyang
 * @Date 2021/10/25 16:57
 */
public class ObjectStreamTest {
    /**
     Serialization process: save java objects in memory to disk or transfer them over the network
     Implementation using ObjectOutputStream
     The output file cannot be opened directly. If you want to view the contents, you need to use ObjectInputStream
     */
    @Test
    public void testOne() {
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
            oos.writeObject(new String("java Is the best language in the world"));
            // Refresh operation
            oos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     Deserialization process: restore the object in the disk file to a java object in memory
     Implementation using ObjectInputStream
     */
    @Test
    public void testTwo() {
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream("object.dat"));
            Object object = ois.readObject();
            String str = (String) object;
            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();
                }
            }
        }
    }
}

Use custom classes to implement serialization and deserialization operations

The user-defined class must meet the following requirements before serialization

  • Implement the Serializable interface (Serializable is an identification interface without any methods to be implemented)
  • The current class provides a global constant: serialVersionUID

be careful:

  1. The order of reading must be consistent with that of writing (if they are of the same type, they can be read directly), otherwise an exception will be reported
  2. ObjectOutputStream and ObjectInputStream cannot serialize static and transient decorated member variables
  3. If the subclass attribute in the custom class is not serializable, an error will also be reported: NotSerializableException; If you want to execute normally, you need to declare the subclass as serializable
package com.laoyang.test.day6;

import org.junit.Test;
import java.io.*;

/**
 * @ClassName ObjectStreamTest
 * @Description:  Processing flow 6: use of object flow
 * @Author Laoyang
 * @Date 2021/10/25 16:57
 */
public class ObjectStreamTest {
    /**
     * Use custom classes to implement serialization and deserialization operations
     * Serialization operation
     */
    @Test
    public void testThree() {
        ObjectOutputStream oos = null;
//        ObjectInputStream ois = null;
        try {
            // write in
            oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
            oos.writeObject(new String("java Is the best language in the world"));
            // Refresh operation
            oos.flush();
            oos.writeObject(new Person("Xiaobai", 18));
            oos.flush();
            oos.writeObject(new Person("Xiao Hei", 23, new Account(5000)));
            oos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * Deserialization operation
     */
    @Test
    public void testFour() {
        ObjectInputStream ois = null;
        try {
            // When reading, the order of reading must be consistent with that of writing (if they are of the same type, they can be read directly), otherwise an exception will be reported
            ois = new ObjectInputStream(new FileInputStream("object.dat"));
            String str = (String) ois.readObject();
            Person person = (Person) ois.readObject();
            System.out.println(str);
            System.out.println(person);

            /*
             If the Account attribute in the Person class is not serializable, an error will be reported: NotSerializableException
             If you want to execute normally, you need to declare the Account class as serializable
             */
            Person account = (Person) ois.readObject();
            System.out.println(account);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

/**
 * User defined classes implement serialization and deserialization operations
 * Person Class needs to meet the following requirements before serialization
 * 1. Implement the Serializable interface (Serializable is an identification interface without any methods to be implemented)
 * 2. The current class provides a global constant: serialVersionUID
 */
class Person implements Serializable {
    // The difference between defining serialVersionUID and not defining serialVersionUID constant can be tested
    private static final long serialVersionUID = -1806851998099103327L;

    // ObjectOutputStream and ObjectInputStream cannot serialize static and transient decorated member variables
//    private static String name;
//    private transient int age;
    private String name;
    private int age;
    private Account account;

    public Person(String name, int age, Account account) {
        this.name = name;
        this.age = age;
        this.account = account;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", account=" + account +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }
}

/**
 * Custom class, used to test as a parameter of the Person class
 * You can remove or add Serializable for testing to see different test results
 */
// class Account {
class Account implements Serializable {
    private static final long serialVersionUID = 1928731172189653323L;

    private double balance;

    @Override
    public String toString() {
        return "Account{" +
                "balance=" + balance +
                '}';
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    public Account(double balance) {
        this.balance = balance;
    }

    public Account() {
    }
}

idea set quick generation: File > editor > inspections > serialization issues > just tick the Serializable class without 'serialVersionUID'

After setting, click the corresponding class, and then press ALT + enter

Random access file stream

RandomAccessFile class

explain

  • RandomAccessFile is declared under the java.io package, but directly inherits from the java.lang.Object class. And it implements DataInput and DataOutput interfaces, which means that this class can read and write.

  • RandomAccessFile class supports "random access". The program can directly jump to any place of the file to read and write the file

    Only part of the contents of the file can be accessed
    You can append content to an existing file

  • The RandomAccessFile object contains a record pointer to indicate the location of the current read / write location.

    RandomAccessFile class object can move the record pointer freely:

    long getFilePointer(): get the current position of the file record pointer

    void seek(long pos): position the file record pointer to the pos position

use

  • constructor

    public RandomAccessFile(File file, String mode)

    public RandomAccessFile(String name, String mode)

  • To create an instance of RandomAccessFile class, you need to specify a mode parameter, which 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
    
  • If the mode is read-only r. Instead of creating a file, an existing file will be read. If the read file does not exist, an exception will occur. If the mode is rw read / write. If the file does not exist, it will be created. If it does exist, it will not be created.

other

We can use the RandomAccessFile class to realize a multi-threaded breakpoint download function. Friends who have used the download tool know that before downloading, two temporary files will be created, one is an empty file with the same size as the downloaded file, and the other is a file that records the location of the file pointer. Each time we pause, the last pointer will be saved, Then, during breakpoint download, it will continue to download from the last place, so as to realize the function of breakpoint download or upload. Interested friends can realize it by themselves.

For example, when using Baidu cloud or Xunlei to download a file, we can open the corresponding save location before the download is completed. There is already a file. This file belongs to a temporary file. If the download is suspended due to the sudden lack of network at this time, we will download from the last suspended location next time, Instead of downloading from scratch, this belongs to a multi-threaded breakpoint download.

case

explain

  1. RandomAccessFile directly inherits the java.lang.Object class and implements the DataInput and DataOutput interfaces
  2. RandomAccessFile can be used as both an input stream and an output stream
  3. If RandomAccessFile is used as the output stream, if the file written to does not exist, it will be automatically created during execution
    If the file written to exists, the original file content will be overwritten (by default, it is overwritten from the beginning)
  4. You can "insert" data into RandomAccessFile through related operations

Use of RandomAccessFile class

constructor

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

To create an instance of RandomAccessFile class, you need to specify a mode parameter, which 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

Generally, r and rw are enough

package com.laoyang.test.day7;

import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * @ClassName RandomStorageFileStreamTest
 * @Description:  Random access file stream
 * @Author Laoyang
 * @Date 2021/10/26 9:32
 */
public class RandomAccessFileStreamTest {
    @Test
    public void testOne() {
        RandomAccessFile rafDataInput = null;
        RandomAccessFile rafDataOutput = null;
        try {
            // 1. Instantiate the object of the flow
            rafDataInput = new RandomAccessFile(new File("2.jpg"), "r");
            rafDataOutput = new RandomAccessFile(new File("234.jpg"), "rw");

            // 2. Read / write operation
            byte[] buffer = new byte[10];
            int read = rafDataInput.read(buffer);
            while (read != -1) {
                rafDataOutput.write(buffer, 0, read);
                read = rafDataInput.read(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 3. Close the flow
            if (rafDataOutput != null) {
                try {
                    rafDataOutput.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (rafDataInput != null) {
                try {
                    rafDataInput.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

About the file overwrite operation when RandomAccessFile is only used as output stream

When the specified file does not exist, a file will be created, and then the data will be written to the new file; If the file exists, it will be overwritten from the beginning. For example, the data in helloA.txt is Hello. When AAA is written, the data becomes AAA

package com.laoyang.test.day7;

import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * @ClassName RandomStorageFileStreamTest
 * @Description:  Random access file stream
 * @Author Laoyang
 * @Date 2021/10/26 9:32
 */
public class RandomAccessFileStreamTest {
    /**
     * About the file overwrite operation when RandomAccessFile is only used as output stream
     */
    @Test
    public void testTwo() {
        RandomAccessFile raf = null;
        try {
            File file = new File("helloA.txt");
            /*
             When the specified file does not exist, a file will be created and the data will be written to the new file
             If it exists, it will be overwritten from the beginning. For example, the data in helloA.txt is Hello. When AAA is written, the data becomes AAA
             */
//            raf = new RandomAccessFile("helloAAA.txt", "rw");
            raf = new RandomAccessFile(file, "rw");
            // Adjust the pointer to the position marked 3
//            raf.seek(3);
            // If you want to append data from the end of the file, you can point to the corner mark position of the last character of the file
            raf.seek(file.length());
            // If the specified file exists, write() is equivalent to an overwrite operation
            raf.write("AAA".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (raf != null)
                    raf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

RandomAccessFile to achieve data insertion effect

General logic:

  1. Start reading from the corresponding pointer position, get all the data behind the insertion position, and then store it with StringBuilder

  2. Write the corresponding data from the pointer position

  3. First perform a write operation on the data to be inserted, and then write the data in StringBuilder

    The data written by StringBuilder is followed by the data written last time. Basically, it can also be understood as overwriting the original data.

    For example, the original data is: Hello World. When AAA is inserted for the first time, the result becomes: Hello World. When it is inserted for the second time, it becomes Hello World
    It is equivalent to that "lo World" is stored in StringBuilder. The second insertion is only to recover the data overwritten during insertion.

package com.laoyang.test.day7;

import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * @ClassName RandomStorageFileStreamTest
 * @Description:  Random access file stream
 * @Author Laoyang
 * @Date 2021/10/26 9:32
 */
public class RandomAccessFileStreamTest {
    /**
     * Use RandomAccessFile to achieve data insertion effect
     */
    @Test
    public void testThree() {
        RandomAccessFile raf = null;
        try {
            File file = new File("helloA.txt");
            raf = new RandomAccessFile(file, "rw");
            // Read from the position of pointer 3
            raf.seek(3);
            // Save all data after pointer 3 to StringBuilder
            StringBuilder builder = new StringBuilder((int) file.length());
            byte[] buffer = new byte[10];
            int read = raf.read(buffer);
            while (read != -1) {
                builder.append(new String(buffer, 0, read));
                read = raf.read(buffer);
            }
            System.out.println(builder.toString());
            // Call back the pointer and write ABC
            raf.seek(3);
            raf.write("ABC".getBytes());

            // Writes data from StringBuilder to a file
            raf.write(builder.toString().getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (raf != null) {
                try {
                    raf.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Use of getFilePointer() method

package com.laoyang.test.day7;

import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * @ClassName RandomStorageFileStreamTest
 * @Description:  Random access file stream
 * @Author Laoyang
 * @Date 2021/10/26 9:32
 */
public class RandomAccessFileStreamTest {
    /**
     * getFilePointer() Use of methods
     * Function: get the current position of file record pointer
     * @throws IOException
     */
    @Test
    public void test() {
        RandomAccessFile file = null;
        try {
            file = new RandomAccessFile(new File("helloA.txt"), "rw");
            System.out.println(file.getFilePointer());  // 0

            file.seek(3);
            System.out.println(file.getFilePointer());  // 3
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (file != null) {
                try {
                    file.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Thinking: replace StringBuilder with ByteArrayOutputStream to implement the insertion of RandomAccessFile

package com.laoyang.test.day7;

import org.junit.Test;
import java.io.*;

/**
 * @ClassName RandomStorageFileStreamTest
 * @Description:  Thinking: replace StringBuilder with ByteArrayOutputStream to implement the insertion of RandomAccessFile
 * @Author Laoyang
 * @Date 2021/10/26 11:04
 */
public class ByteArrayOutputStreamTest {
	@Test
	public void test1() {
		FileInputStream fis = null;
		try {
			fis = new FileInputStream("helloA.txt");
			String info = readStringFromInputStream(fis);
			System.out.println(info);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * read operation
	 * @param fis
	 * @return
	 * @throws IOException
	 */
	private String readStringFromInputStream(FileInputStream fis) throws IOException {
		// Method 1: possible garbled code
//		 String content = "";
//		 byte[] buffer = new byte[1024];
//		 int len;
//		 while((len = fis.read(buffer)) != -1){
//		 content += new String(buffer);
//		 }
//		 return content;

		// Method 2: BufferedReader
//		BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
//		char[] buf = new char[10];
//		int len;
//		String str = "";
//		while ((len = reader.read(buf)) != -1) {
//			str += new String(buf, 0, len);
//		}
//		return str;

		// Method 3: avoid garbled code
		 ByteArrayOutputStream baos = new ByteArrayOutputStream();
		 byte[] buffer = new byte[10];
		 int len = fis.read(buffer);
		 while (len != -1) {
			 baos.write(buffer, 0, len);
			 len = fis.read(buffer);
		 }
		 return baos.toString();
	}

	/**
	 * Insert operation
	 */
	@Test
	public void testByteArrayOutputStream() {
		RandomAccessFile raf = null;
		try {
			File file = new File("helloA.txt");

			raf = new RandomAccessFile(file, "rw");

			raf.seek(3);
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			byte[] buffer = new byte[10];
			int read = raf.read(buffer);
			while (read != -1) {
				baos.write(buffer, 0, read);
				read = raf.read(buffer);
			}
			raf.seek(3);
			raf.write("QQ".getBytes());
			raf.write(baos.toString().getBytes());
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (raf != null) {
				try {
					raf.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

Here is a demonstration of using ByteArrayOutputStream to implement read and write operations

Use of Path, Paths and Files classes in NIO.2

Java NIO overview

  1. Java NIO (New IO, non blocking IO) is a set of IO API introduced from Java version 1.4, which can replace the standard Java IO API. NIO has the same function and purpose as the original IO, but it is used in a completely different way. NIO supports buffer oriented (IO is stream oriented) and channel based IO operations. NIO will read and write files in a more efficient way.
  2. Java API provides two sets of NIO, one for standard input and output NIO and the other for network programming NIO.
|-----java.nio.channels.Channel
	  |-----FileChannel:Process local files
	  |-----SocketChannel: TCP Network programming client Channel
	  |-----ServerSocketChannel:TCP Server side of network programming Channel
	  |-----DatagramChannel: UDP Of sender and receiver in network programming Channel

NIO.2

With the release of JDK 7, Java has greatly extended NIO and enhanced its support for file processing and file system features, so that we call them NIO.2. NIO has become an increasingly important part of file processing because of some functions provided by NIO.

Path, Paths, and Files core API s

  • Early Java only provided a File class to access the File system, but the function of the File class is relatively limited and the performance of the methods provided is not high. Moreover, most methods only return failure when there is an error and do not provide exception information.

  • In order to make up for this deficiency, NIO. 2 introduces the path interface, which represents a platform independent path and describes the location of files in the directory structure. Path can be regarded as an upgraded version of the File class, and the actually referenced resources may not exist.

  • In the past, IO operations were written like this:

    import java.io.File; 
    File file = new File("index.html"); 
    
  • But in Java 7, we can write this:

    import java.nio.file.Path;  
    import java.nio.file.Paths;  
    Path path = Paths.get("index.html")
    
  • Meanwhile, NIO.2 also provides files and paths tool classes under the java.nio.file package. Files contains a large number of static tool methods to operate files; Paths contains two static factory methods that return Path.

  • The static get() method provided by the Paths class is used to obtain the Path object:

    static Path get(String first, String ... more): Used to concatenate multiple characters into a path
    static Path get(URI uri): Return specified uri Corresponding Path route
    

Path common methods

methodeffect
String toString()Returns the string representation of the calling Path object
boolean startsWith(String path)Determine whether to start with path path
boolean endsWith(String path)Determine whether to end with path
boolean isAbsolute()Determine whether it is an absolute path
Path getParent()The returned Path object contains the entire Path, not the file Path specified by the Path object
Path getRoot()Returns the root Path of the calling Path object
Path getFileName()Returns the file name associated with the calling Path object
int getNameCount()Returns the number of elements following the Path root directory
Path getName(int idx)Returns the path name of the specified index location idx
Path toAbsolutePath()Returns the calling Path object as an absolute Path
Path resolve(Path p)Merge two paths and return the Path object corresponding to the merged Path
File toFile()Convert Path to an object of File class

Files common methods

Description: java.nio.file.Files is a tool class for operating files or directories.

common method

methodeffect
Path copy(Path src, Path dest, CopyOption ... how)Copy of files
Path createDirectory(Path path, FileAttribute<?> ... attr)Create a directory
Path createFile(Path path, FileAttribute<?> ... arr)Create a file
void delete(Path path)Delete a file / directory. If it does not exist, an error will be reported
void deleteIfExists(Path path)If the file / directory corresponding to Path exists, delete it
Path move(Path src, Path dest, CopyOption...how)Move src to dest position
long size(Path path)Return path specifies the size of the file

Common methods · for judgment

methodeffect
boolean exists(Path path, LinkOption ... opts)Determine whether the file exists
boolean isDirectory(Path path, LinkOption ... opts)Determine whether it is a directory
boolean isRegularFile(Path path, LinkOption ... opts)Determine whether it is a file
boolean isHidden(Path path)Determine whether it is a hidden file
boolean isReadable(Path path)Determine whether the file is readable
boolean isWritable(Path path)Determine whether the file is writable
boolean notExists(Path path, LinkOption ... opts)Determine whether the file does not exist

Common methods and contents for operation

methodeffect
SeekableByteChannel newByteChannel(Path path, OpenOption...how)Gets the connection to the specified file and how specifies the opening method.
DirectoryStream newDirectoryStream(Path path) Open the directory specified by path
InputStream newInputStream(Path path, OpenOption...how)Get InputStream object
OutputStream newOutputStream(Path path, OpenOption...how)Get OutputStream object

case

Use of Path

  1. jdk 7.0 introduces three classes: Path, Paths and Files.

  2. These three classes are declared under the java.nio.file package.

  3. Path can be regarded as an upgraded version of the java.io.File class. It can also represent files or file directories, independent of the platform

  4. How to instantiate a Path: using Paths

    static Path get(String first, String ... more): Used to concatenate multiple characters into a path
    static Path get(URI uri): Return specified uri Corresponding Path route
    
package com.laoyang.test.day8;

import org.junit.Test;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * @ClassName RandomStorageFileStreamTest
 * @Description:  Path Use of classes
 * @Author Laoyang
 * @Date 2021/10/26 11:17
 */
public class PathTest {
    /**
     * How to instantiate a Path using Paths
     */
    @Test
    public void test1() {
        Path path1 = Paths.get("F:\\nio\\hello.txt");     // new File(String filepath)
        Path path2 = Paths.get("F:\\", "nio\\hello.txt"); // new File(String parent,String filename);

        System.out.println(path1);
        System.out.println(path2);

        Path path3 = Paths.get("F:\\", "nio");
        System.out.println(path3);
    }

    /**
     * Path Common methods in
     */
    @Test
    public void test2() {
        Path path1 = Paths.get("F:\\", "nio\\nio1\\nio2\\hello.txt");
        Path path2 = Paths.get("hello.txt");

//    String toString(): returns the string representation of the calling Path object
        System.out.println(path1);

//    boolean startsWith(String path): judge whether to start with the path path
        System.out.println(path1.startsWith("F:\\nio"));
        
//    boolean endsWith(String path): judge whether to end with path path
        System.out.println(path1.endsWith("hello.txt"));
        
//    boolean isAbsolute(): judge whether it is an absolute path
        System.out.println(path1.isAbsolute() + "~");
        System.out.println(path2.isAbsolute() + "~");
        
//    Path getParent(): the returned path object contains the entire path, not the file path specified by the path object
        System.out.println(path1.getParent());
        System.out.println(path2.getParent());
        
//    Path getRoot(): returns the root path of the calling path object
        System.out.println(path1.getRoot());
        System.out.println(path2.getRoot());
        
//    Path getFileName(): returns the file name associated with the calling path object
        System.out.println(path1.getFileName() + "~");
        System.out.println(path2.getFileName() + "~");
        
//    int getNameCount(): returns the number of elements behind the Path root directory
//    Path getName(int idx): returns the path name of the specified index location idx
        for (int i = 0; i < path1.getNameCount(); i++) {
            System.out.println(path1.getName(i) + "*****");
        }

//    Path toAbsolutePath(): returns the calling path object as an absolute path
        System.out.println(path1.toAbsolutePath());
        System.out.println(path2.toAbsolutePath());
        
//    Path resolve(Path p): merge two paths and return the path object corresponding to the merged path
        Path path3 = Paths.get("F:\\", "nio");
        Path path4 = Paths.get("nioo\\hi.txt");
        path3 = path3.resolve(path4);
        System.out.println(path3);

//    File toFile(): converts Path to an object of file class
        File file = path1.toFile();//Path - > file conversion

        Path newPath = file.toPath();//File - > path conversion
    }
}

Conversion between File and Path:

Path - > file conversion: use toFile() method

Fil e - > path conversion: use the toPath() method

Use of Files tool class

package com.laoyang.test.day8;

import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.*;
import java.util.Iterator;

/**
 * @ClassName RandomStorageFileStreamTest
 * @Description:  Files Use of tool classes: tool classes that manipulate files or directories
 * @Author Laoyang
 * @Date 2021/10/26 11:23
 */
public class FilesTest {
   @Test
   public void test1() throws IOException{
      Path path1 = Paths.get("F:\\nio", "hello.txt");
      Path path2 = Paths.get("heihei.txt");
      
//    Path copy(Path src, Path dest, CopyOption... how): copy files
      //To copy successfully, the physical file corresponding to path1 must exist. The file corresponding to path1 is not required.
//    Files.copy(path1, path2, StandardCopyOption.REPLACE_EXISTING);
      
//    Path createdirectory (path, fileattribute <? >... attr): create a directory
      //To execute successfully, the physical file directory corresponding to path does not exist. Once it exists, an exception is thrown.
      Path path3 = Paths.get("F:\\nio\\nio1");
//    Files.createDirectory(path3);
      
//    Path CreateFile (path, fileattribute <? >... arr): create a file
      //To execute successfully, the physical file corresponding to path does not exist. Once it exists, an exception is thrown.
      Path path4 = Paths.get("F:\\nio\\hi.txt");
//    Files.createFile(path4);
      
//    Void delete (path): deletes a file / directory. If it does not exist, an error is reported
//    Files.delete(path4);
      
//    Void deleteifexists (path path): if the file / directory corresponding to path exists, delete it. If it does not exist, normal execution ends
      Files.deleteIfExists(path3);
      
//    Path move(Path src, Path dest, CopyOption... how): move src to dest
      //To execute successfully, the physical file corresponding to src needs to exist, and the file corresponding to dest does not.
//    Files.move(path1, path2, StandardCopyOption.ATOMIC_MOVE);
      
//    Long size (path): returns the size of the specified file
      long size = Files.size(path2);
      System.out.println(size);
   }

   @Test
   public void test2() throws IOException{
      Path path1 = Paths.get("F:\\nio", "hello.txt");
      Path path2 = Paths.get("heihei.txt");
       
//    Boolean exists (path, linkoption... opts): judge whether the file exists
      System.out.println(Files.exists(path2, LinkOption.NOFOLLOW_LINKS));

//    Boolean isdirectory (path, linkoption... opts): judge whether it is a directory
      //Do not require the physical file corresponding to this path to exist.
      System.out.println(Files.isDirectory(path1, LinkOption.NOFOLLOW_LINKS));

//    Boolean isregularfile (path, linkoption... opts): judge whether it is a file

//    Boolean ishidden (path): judge whether it is a hidden file
       
      //The physical file corresponding to this path needs to exist. To determine whether it is hidden. Otherwise, throw the exception.
//    System.out.println(Files.isHidden(path1));

//    Boolean isreadable (path): judge whether the file is readable
      System.out.println(Files.isReadable(path1));
       
//    Boolean iswritable (path): judge whether the file is writable
      System.out.println(Files.isWritable(path1));
       
//    Boolean notexists (path, linkoption... opts): judge whether the file does not exist
      System.out.println(Files.notExists(path1, LinkOption.NOFOLLOW_LINKS));
   }

   /**
    * StandardOpenOption.READ:Indicates that the corresponding Channel is readable.
    * StandardOpenOption.WRITE: Indicates that the corresponding Channel is writable.
    * StandardOpenOption.CREATE: If the file to be written out does not exist, it is created. Ignore if present
    * StandardOpenOption.CREATE_NEW: If the file to be written out does not exist, it is created. If so, throw the exception
    */
   @Test
   public void test3() throws IOException{
      Path path1 = Paths.get("F:\\nio", "hello.txt");

//    InputStream newinputstream (path, openoption... how): get the InputStream object
      InputStream inputStream = Files.newInputStream(path1, StandardOpenOption.READ);

//    OutputStream newoutputstream (path, openoption... how): get the OutputStream object
      OutputStream outputStream = Files.newOutputStream(path1, StandardOpenOption.WRITE,StandardOpenOption.CREATE);


//    Seekablebytechannel newbytechannel (path, openoption... how): gets the connection to the specified file, and how specifies the opening method.
      SeekableByteChannel channel = Files.newByteChannel(path1, StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE);

//    Directorystream < Path > newdirectorystream (path): open the directory specified in path
      Path path2 = Paths.get("F:\\teach");
      DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path2);
      Iterator<Path> iterator = directoryStream.iterator();
      while(iterator.hasNext()){
         System.out.println(iterator.next());
      }
   }
}

Manually import third-party jar packages in IDEA

  1. Right click the corresponding module, click New, and then create a common folder for storing third-party jar packages (the folder name is usually lib)

  1. Copy the corresponding jar package to the newly created folder. At this time, the jar package cannot be used

  1. Right click the corresponding jar package, click Add as Library, select the module to add to, and then click OK

Use of third-party jar packages

package com.laoyang.test.day9;

import org.apache.commons.io.FileUtils;
import org.junit.Test;
import java.io.File;
import java.io.IOException;

/**
 * @ClassName FileUtilsTest
 * @Description:  Use of third-party jar packages
 * @Author Laoyang
 * @Date 2021/10/26 11:25
 */
public class FileUtilsTest {
    @Test
    public void testOne() {
        File fileA = new File("2.jpg");
        File fileB = new File("666.jpg");
        try {
            FileUtils.copyFile(fileA, fileB);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

import org.apache.commons.io.FileUtils; The jar package we just imported is used

Benefits: more convenient and fast

Posted by dankstick on Fri, 29 Oct 2021 21:05:20 -0700