Explain IO flow knowledge in simple terms - basic flow

Posted by besa on Fri, 04 Mar 2022 06:13:28 +0100

There are thousands of people in the vast sea. Thank you for seeing here this second. I hope my article is helpful to you!

May you keep your love and go to the mountains and seas in the future!

I/O basic flow

Java operates data through streams. IO streams are used to handle data transmission between devices, upload files and download files. Java objects used to operate streams are all in io packages. The stream is a set of orderly data sequence with starting point and ending point. Its essence is data transmission. According to the characteristics of data transmission, the stream is abstracted into various types to facilitate more intuitive data operation.

Function: establish a transport channel for data source and destination. โ™’

1. File class ๐Ÿ“„

Most IO stream operations are File operations, so Java provides the File class for us to operate files ๐Ÿ“ง๐Ÿ“ง.

1.1 general ๐Ÿ“œ

java. io. The file class is an abstract representation of file and directory pathnames. File class is an object that encapsulates files and folders in the file system. Files and folders can be operated through the idea of objects. It can be mainly used for the creation, search and deletion of files and directories.

be careful ๐Ÿ’ก: File represents file and directory information, not the contents of the file.

1.2 construction method ๐Ÿ—„๏ธ

public File(String pathname) {} //Absolute path of the file

public File(String parent, String child) {}//Specify the absolute path of the parent file and the absolute path of the child file

public File(File parent, String child) {}//Specify the relative path of parent file and child file

public File(URI uri) {} //URI address of the file

//These two File constructors cannot be called outside the class
private File(String pathname, int prefixLength) {}

private File(String child, File parent) {}public File(String pathname) {}

Can see ๐Ÿ˜ฌ๐Ÿ˜ฌ๐Ÿ˜ฌ๏ผŒ There are 6 constructors of File class: 4 public constructors and 2 private constructors.

The common construction methods are:

  • public File(String pathname): create a new File instance by converting the given pathname string to an abstract pathname.
  • public File(String parent, String child): creates a new File instance from the parent pathname string and the child pathname string.
  • public File(File parent, String child): creates a new File instance from the parent abstract pathname and child pathname strings.

๐Ÿฎ See the following code demonstration:

//public File(String pathname) / / file pathname
String pathName = "E:\\aaa.txt";
File file = new File(pathName);

//public File(String parent, String child) string through parent path and child path
String parent = "E:\\aaa";
String child = "bbb.txt";
File file2 = new File(parent, child);

// public File(File parent, String child) uses the parent File object and the child path string
File parentDir = new File("E:\\aaa");
String child2 = "bbb.txt";
File file3 = new File(parentDir, child2);

be careful ๐Ÿ’ฐ: I wonder if you have noticed that the file path name I wrote is like "E:\aaa", but isn't our file path like "E:\aaa"?

Because \ is an escape character in the string, if you are just a \, you will think that you are an escape character, so you need two.

Tips:

  1. A File object represents a File or directory that actually exists in the hard disk.
  2. Whether there is a File or directory in this path does not affect the creation of the File object.

1.3 common methods of file โšช

The following required files are based on this a.txt:

1.3.1 acquisition function ๐Ÿ”ด

  • public String getAbsolutePath(): returns the absolute pathname string of this File.
  • public String getPath(): converts this File to a pathname string.
  • public String getName(): returns the name of the File or directory represented by this File.
  • public long length(): returns the length of the File represented by this File.
  • public long lastModified(): gets the last modification time, in milliseconds

Code demonstration:

public class FileTest {
    public static void main(String[] args) {
        File file = new File("E:\\demo\\a.txt");

        //public String getAbsolutePath(): get absolute path
        System.out.println("getAbsolutePath: " + file.getAbsolutePath());//getAbsolutePath: E:\demo\a.txt

        //public String getPath(): get relative path
        System.out.println("getPath: " + file.getPath());//getPath: E:\demo\a.txt

        //public String getName(): get the name
        System.out.println("getName: " + file.getName());//getName: a.txt

        //public long length(): get the length. Number of bytes
        System.out.println("length: " + file.length());//length: 20

        //public long lastModified(): gets the last modification time, in milliseconds
        System.out.println("lastModified: " + file.lastModified());//lastModified: 1606645407343

        //Convert the format to millisecond value.
        Date time = new Date(file.lastModified());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String s = sdf.format(time);
        System.out.println(s);//2020-11-29 18:23:27
    }
}

It must be unnecessary to talk about this. You can use it after reading it. Just call it directly.

1.3.2 judgment function ๐ŸŸ 

  • public boolean isDirectory(): judge whether it is a directory
  • public boolean isFile(): judge whether it is a file
  • public boolean exists(): judge whether it exists
  • public boolean canRead(): judge whether it is readable
  • public boolean canWrite(): judge whether it is writable
  • public boolean isHidden(): judge whether to hide

As usual, continue with a wave of demonstration and get up:

public class FileTest2 {
    public static void main(String[] args) {
        File file = new File("E:\\demo\\a.txt");

        //public boolean isDirectory(): judge whether it is a directory
        System.out.println("isDirectory: " + file.isDirectory());//isDirectory: false

        //public boolean isFile(): judge whether it is a file
        System.out.println("isFile: " + file.isFile());//isFile: true

        //public boolean exists(): judge whether it exists
        System.out.println("exists: " + file.exists());//exists: true

        //public boolean canRead(): judge whether it is readable
        System.out.println("canRead: " + file.canRead());//canRead: true

        //public boolean canWrite(): judge whether it is writable
        System.out.println("canWrite: " + file.canWrite());//canWrite: true

        //public boolean isHidden(): judge whether to hide
        System.out.println("isHidden: " + file.isHidden());//isHidden: false
    }
}

No more, look at the code! Just read it!

1.3.3 create function ๐ŸŸก

  • public boolean createNewFile(): create a file. If such a file exists, it will not be created
  • public boolean mkdir(): create a folder. If such a folder exists, it will not be created
  • public boolean mkdirs(): create a folder. If the parent folder does not exist, it will help you create it

First look at the file information before creation:

Then, as usual, continue with a wave of demonstration and walk up:

public class FileTest3 {
    public static void main(String[] args) throws IOException {
        //public boolean mkdir(): create a folder. If such a folder exists, it will not be created
        // Create a folder hello under the e disk folder demo
        File file = new File("E:\\demo\\hello"); //According to the above file information, you can see that there is no hello folder
        System.out.println("mkdir: " + file.mkdir());
        System.out.println("Then judge whether the following folder exists: " + file.exists());

        //public boolean createNewFile(): create a file. If such a file exists, it will not be created
        //Create a file hello. In the folder Hello under the demo directory of disk e txt
        File file2 = new File(file,"\\hello.txt");//The hello folder has been created above
        System.out.println("createNewFile: " + file2.createNewFile());
        System.out.println("Then judge whether the file exists: " + file2.exists());

        //public boolean mkdirs(): create a folder. If the parent folder does not exist, it will help you create it
        File file3 = new File("E:\\demo\\world\\world");//Can I create two-level folders directly
        System.out.println("mkdirs: " + file3.mkdirs());
        System.out.println("Then judge whether the following folder exists: " + file3.exists());
    }
}

The first execution result can be seen:

mkdir: true
 Then judge whether the following folder exists: true
createNewFile: true
 Then judge whether the file exists: true
mkdirs: true
 Then judge whether the following folder exists: true

Now that the files or folders have been created, what will happen if we run them again?

mkdir: false
 Then judge whether the following folder exists: true
createNewFile: false
 Then judge whether the file exists: true
mkdirs: false
 Then judge whether the file exists: true

Method calls are false, which means that if there are files or folders, they will not be created.

A small question, which of the created methods is likely to throw an exception? Look at the code and think it may go wrong

File file4 = new File("E:\\world\\world2"); 
System.out.println("mkdir: " + file4.mkdir());

File file5 = new File("E:\\world\\world2");
System.out.println("mkdirs: " + file5.mkdirs());

File file6 = new File("E:\\helloWorld\\helloWorld2"); 
System.out.println("createNewFile: " + file6.createNewFile());

The operation results can be seen as follows:

mkdir: false
mkdirs: true
Exception in thread "main" java.io.IOException: The system cannot find the specified path.
	at java.io.WinNTFileSystem.createFileExclusively(Native Method)
    at java.io.File.createNewFile(File.java:1012)
	at com.it.test1.FileTest3.main(FileTest3.java:33) 

Summary โฌœ:

  1. If mkdir exists in a folder or the parent directory does not exist, it will return false, that is, it will not be created, otherwise it will be created.
  2. If dirs does not exist, MKS will be returned.
  3. createNewFile will return false if a file exists, that is, it will not be created, otherwise it will be created. If the parent directory does not exist, an error will be reported, and the system cannot find the IOException of the specified path.

1.3.4 delete function ๐ŸŸข

Now let's look at the folder information:

In the above creation process, we already have the Hello folder and hello under the directory Txt and the world folder under the world folder.

  • public boolean delete(): delete the File or directory represented by this File.

If you don't say much, demonstrate on the:

public class FileTest4 {
	public static void main(String[] args) {
        //public boolean delete(): delete the File or directory represented by this File.
        //Next, let's delete the previously created file.
        //1. We delete the hello in the Hello folder txt
        File file = new File("e:\\demo\\hello\\hello.txt");
        System.out.println("delete hello.txt: " + file.delete());

        //2. Shall I delete it again? What will it return?
        System.out.println("delete hello.txt: " + file.delete());

        //3. Next, I want to delete the hello folder.
        File file2 = new File("e:\\demo\\hello");
        System.out.println("delete hello folder:" + file2.delete());

        //4. Next, I want to delete the world folder under demo directly. We know there is a world folder in it. What will happen?
        File file3 = new File("e:\\demo\\world");
        System.out.println("delete world folder:" + file3.delete());
    }
}

Can we guess whether the last deletion of the world folder is successful?

Run program results:

delete hello.txt: true
 delete hello.txt: false
 delete hello folder: true
 delete world folder: false

be careful ๐Ÿ“‚:

  1. You can see if we delete hello Txt, and then delete, it returns false, that is, the deletion fails.

  2. If there are files or folders under the folder, the deletion will also fail. That is, if we want to delete the world folder under the demo directly, we will fail because there are still folders in it.

  3. For example, when we delete files, does it go to the recycle bin? When we delete files with Java, do we also go to the recycle bin?

You can see that our recycle bin is empty. Instead of going to the recycle bin, it was really deleted by the JVM.

1.3.5 other functions ๐Ÿ”ต

  1. Rename function

    • Public Boolean renameto (file): Rename
    public class FileTest5 {
        public static void main(String[] args) {
            //public boolean renameTo(File file)
            File file = new File("e:\\demo\\a.txt");
            System.out.println("renameTo:  " + file.renameTo(new File("e:\\demo\\b.txt")));//renameTo:  true
        }
    }
    

    Program running results:

    renameTo:  true
    

    Then let's look at the file information:

  1. Absolute path and relative path

    • Absolute path: the path starting from the drive letter. This is a complete path. For example: e \ \ demo a.txt.

    • Relative path: relative to the path of the project directory, this is a convenient path, which is often used in development. For example: a.txt.

      public class FileTest6 {
          public static void main(String[] args) {
              // BBB under disk E Java file
              File f = new File("E:\\bbb.java");
              System.out.println(f.getAbsolutePath());
      
              // BBB under Project Java file
              File f2 = new File("bbb.java");
              System.out.println(f2.getAbsolutePath());
          }
      }
      

      The operation results are as follows:

      E:\bbb.java
      E:\IdeaWorkSpace\project_File\bbb.java
      
  2. Directory traversal

    • public String[] list(): returns a String array representing all sub files or directories in the File directory.
    • public File[] listFiles(): returns a File array representing all sub files or directories in the File directory.

    Continue with the demonstration as follows:

    public class FileTest7 {
        public static void main(String[] args) {
            File dir = new File("e:\\demo");
            //public String[] list(): returns a String array representing all sub files or directories in the File directory.
            //Get the name of the file and folder in the current directory.
            String[] names = dir.list();
            for(String name : names){
                System.out.println(name);
            }
    
            //public File[] listFiles(): returns a File array representing all sub files or directories in the File directory.
            //Get the files and folder objects in the current directory. As long as you get the file objects, you can get more information
            File[] files = dir.listFiles();
            for (File file : files) {
                System.out.println(file);
            }
        }
    }
    

    Program running results:

    aaa
    b.txt
    bbb
    e:\demo\aaa
    e:\demo\b.txt
    e:\demo\bbb
    

    be careful ๐Ÿ“ฏ: The File object that calls the listFiles method must represent the actual directory, otherwise it returns null and cannot be traversed.

1.3.6 summary ๐ŸŸฃ

  1. File can be used to represent information about files and directories, but it does not represent the contents of the file. You can read and write files in subsequent IO stream operations.
  2. Whether there is a File or directory in this path does not affect the creation of the File object. Although there is no problem creating the File object, the reference to the File object in subsequent operations may lead to an error.
  3. The introduction of common methods is also completed one by one. There is no need to write it again here. Hey hey!

2. First glimpse of IO flow ๐ŸŒ‘

Finally, it's our key topic. What is IO flow?

2.1 what is IO flow ๐ŸŒ’

In life, you may need to use U SB flash disk to transfer files. This kind of data transmission can be regarded as a kind of data flow. According to the flow direction and based on the memory, it is divided into input and output, that is, the flow to the memory is the input flow and the output flow out of the memory.

Java operates data through streams. IO streams are used to handle data transmission between devices, upload files and download files. Java objects used to operate streams are all in io packages.

2.2 classification of IO ๐ŸŒ“

You can see:

  • According to the different data flow direction, it can be divided into input flow and output flow
  • According to different types of processing data, it can be divided into character stream and byte stream
  • Top level parent
Input streamOutput stream
Byte streamByte input stream
InputStream
Byte output stream
OutputStream
Character streamCharacter input stream
Reader
Character output stream
Writer

The above is just a list of common classes. If you need to see more classes, you can check the API. ๐Ÿคช๐Ÿคช๐Ÿคช

2.3 concept of character byte stream and input / output stream ๐ŸŒ”

2.3.1 character stream and byte stream ๐ŸŒ•

Origin of character stream: because of different data encoding, there is a stream object for efficient operation of characters. The essence is to check the specified code table when reading based on byte stream. Difference between byte stream and character stream:

  • The reading and writing units are different: the byte stream is in bytes (8bit) and the character stream is in characters. The characters are mapped according to the code table, and multiple bytes may be read at a time.

  • Different processing objects: byte stream can process all types of data (such as pictures, avi, etc.), while character stream can only process character type data.

    conclusion ๐Ÿ„: Whenever dealing with plain text data, character streams are preferred. In addition, byte streams are used.

2.3.2 input and output streams ๐ŸŒ–

The input stream can only be read and the output stream can only be written. Different streams need to be used in the program according to the different characteristics of the data to be transmitted.

3. Byte stream ๐Ÿ‡

3.1 in the file world, everything is a byte ๐Ÿˆ

We need to know that all file data (text, pictures, videos, etc.) are stored in the form of binary numbers, one byte by one, so it is the same when transmitting. Therefore, byte stream can transfer any file data. When operating a stream, we should always make it clear that no matter what kind of stream object is used, the underlying transmission is always binary data.

Parent class of 3.2 byte output stream (OutputStream) ๐Ÿ‰

OutputStream is the base class of all byte output streams and a superclass representing all classes of byte output streams. The main function is to write out the specified byte information to the destination. It formulates some specifications and methods for the byte output stream of the whole system.

3.2.1. Let's take a look at his architecture first ๐ŸŠ

  • FileOutputStream: byte File output stream is used to write data to File and other locations from the program.
  • FilterOutputStream: the decorator is in decorator mode, and the specific decorators should inherit it. Therefore, it is used to decorate other streams under the subclass of this class, that is, the processing class.
  • ObjectOutputStream: it is also a decoration class for serialization. It is mainly to write out the original data type of Java objects to files to realize the persistent storage of objects.
  • BufferedInputStream: buffered stream is the enhancement of FilterOutputStream decorative stream to improve the efficiency of reading and writing.
  • PrintStream: it is the enhancement of FilterOutputStream decorative stream. It can easily print the values of various data types, which is a convenient output method.
  • DataOutputStream: data output stream, which is used to decorate other output streams.

3.2.2. Methods in OutputStream ๐Ÿ‹

All subsequent inherited subclasses have these methods. The basic byte output stream needs to be written to the file with the write() method, and the resource is closed with the close() method.

3.2.3. FileOutputStream๐ŸŒ

1. Construction method
  • Output File created by the specified File stream (outputFile): output File written by the specified File stream.
  • public FileOutputStream(File file, boolean append): similar to the above, there are multiple attributes, which will be discussed later
  • public FileOutputStream(String name): creates a file output stream and writes it to the file with the specified name.
  • public FileOutputStream(String name, boolean append): similar to the above, there are multiple attributes, which will be discussed later

This is the folder information before the constructor has been created

public class IOTest {
    public static void main(String[] args) throws FileNotFoundException {
        //public FileOutputStream(File file)
        //Create a stream object using a File object
        File file = new File("e:\\demo\\a.txt");
        FileOutputStream fos = new FileOutputStream(file);

        //public FileOutputStream(String name)
        // Create a stream object with a file name
        FileOutputStream fos2 = new FileOutputStream("E:\\demo\\b.txt");
    }
}

There is no a.txt in our, and there is content in b.txt. Let's execute the following code to see what happens:

It can be seen that there are no errors and no information on the console. Let's take a look at the folder information:

Note: when you create a stream object, you must pass in a file path. In this path, if there is no such file, it will be created. If there is this file, the data of this file will be cleared.

Then why? If there is a file, the data will be emptied. I don't want to empty the data in the target file every time I create an output stream object. What should I do?

  • Let's first look at the specific process of the construction method we call:

    public FileOutputStream(File file) throws FileNotFoundException {
        this(file, false);
    }
    
    public FileOutputStream(String name) throws FileNotFoundException {
        this(name != null ? new File(name) : null, false);
    }
    
    public FileOutputStream(File file, boolean append) throws FileNotFoundException {}
    
    public FileOutputStream(File file, boolean append) throws FileNotFoundException {}
    

    It can be found that the constructor containing the append attribute will be called in the end, and append is false.

    The append attribute indicates that if it is true, it means to append data, and false means to empty the original data. The output stream object created in this way can specify whether to append or renew. I added hello to b.txt first. Then we're trying to see if the files are cleared again

    public class AppendDemo {
        public static void main(String[] args) throws FileNotFoundException {
            FileOutputStream fos2 = new FileOutputStream("E:\\demo\\b.txt", true);
        }
    }
    
    After execution, you can see that the file has not been emptied.
    

Think about a few things we did when we created the byte output stream object. Do we think it is not created directly? There are steps at the bottom:

  1. Call system functions to create files.
  2. Create a fos object.
  3. Point the fos object to this file.
2. Write data

Since we want to create a byte output stream, isn't it just to write data? Otherwise, what's the use of creating it? Let's see how to use it:

  1. public void write(int b): write one byte at a time.

    public class WriteTest {
        public static void main(String[] args) throws IOException {
            // Creates an output stream object with a file name
            FileOutputStream fos = new FileOutputStream("E:\\demo\\a.txt");
    		
            //public void write(int b)
            fos.write(97);
    
            fos.close();
            //What happens if you write data after the stream is closed.
            //fos.write(98);//Exception in thread "main" java.io.IOException: Stream Closed
        }
    }
    
    After the execution result, view the file a.txt What you get is:
    a
    

    There are several points to note:

    • Be sure to close the resource:

      In order to make the stream object become garbage, it can be recycled by the garbage collector.

      Notify the system to release the resources related to the file.

    • Why is it written in 97 and then written to the file and turned into character a:

      Because 97 represents the underlying binary data, find the corresponding character a in the character table through this. Finally, a is displayed instead of 97, but the underlying data is 97. Let's look at the complete ASCII code table:

    • If the stream resource is closed, the operation on this stream cannot be continued, otherwise IOException will be reported.

    • Now, we perform IO stream operations. Except that errors may be printed on the console, other operations are performed directly in the file. The results are directly displayed in the file. If you want to see the results, open the file and see it.

  2. public void write(byte[] b, int off, int len): each write starts from the off index, with len bytes. Equivalent to writing part of a byte array.

    public class WriteTest2 {
        public static void main(String[] args) throws IOException {
            // Creates an output stream object with a file name
            FileOutputStream fos = new FileOutputStream("E:\\demo\\a.txt");
    
            //public void write(byte[] b)
            byte[] b = {97, 98, 99, 100, 101};
            fos.write(b);
    
            fos.close();
        }
    }
    
    After the execution result, view the file a.txt What you get is:
    abcde
    
  3. public void write(byte[] b): write one byte array at a time.

    public class WriteTest3 {
        public static void main(String[] args) throws IOException {
            // Creates an output stream object with a file name
            FileOutputStream fos = new FileOutputStream("E:\\demo\\a.txt");
    
    
            //public void write(byte[] b, int off, int len)
            byte[] b = {97, 98, 99, 100, 101};
            fos.write(b,0,3);
    
            fos.close();
        }
    }
    
    After the execution result, view the file a.txt What you get is:
    abc
    
3. Line feed

The above operations seem to be written on one line. Can we wrap lines?

Let me see how to find the line break first?

  • Carriage returns \ r and line breaks \ n:
    • Carriage return: return to the beginning of a line.
    • newline: next line.
  • Line breaks in the system:
    • In Windows system, the end of each line is enter + line feed, that is \ r\n;
    • In Unix system, there is only newline at the end of each line, that is \ n;
    • In MAC system, the end of each line is carriage return, that is \ r. Unified with Linux from Mac OS X.

But now we should use Windows system by default. What we need to join is \ r\n. Let's take a look at the code demonstration:

After the execution result, view the file a.txt What you get is:
epublic class WriteTest4 {
    public static void main(String[] args) throws IOException {
        // Creates an output stream object with a file name
        FileOutputStream fos = new FileOutputStream("E:\\demo\\a.txt");

        //Realize line wrapping after writing each character
        byte[] b = {97, 98, 99, 100, 101};
        for (byte bs : b) {
            fos.write(bs);
            // Write a newline and convert the newline symbol into an array
            fos.write("\r\n".getBytes());
        }

        fos.close();
    }
}

After the execution result, view the file a.txt What you get is:
a
b
c
d
e

Do you think it's troublesome to check the file every time and then confirm whether it has been added successfully. Next, we will learn the input stream in the byte stream and how to read the file.

Parent class of 3.3 byte input stream (InputStream) ๐Ÿ

InputStream is the base class of all byte input streams and a superclass representing all classes of byte input streams. The main function is to read byte information into memory. It formulates some specifications and methods for the byte input stream of the whole system.

3.3.1 let's take a look at its architecture first ๐Ÿฅญ

  • FileInputStream: file input stream. It is usually used to read files.
  • FilterInputStream: the decorator is in the decorator mode, and the specific decorators should inherit it. Therefore, under the subclass of this class, it is used to decorate other streams, that is, the processing class.
  • BufferedInputStream: buffered stream. It decorates and enhances the processing stream. There will be a buffer area inside to store bytes. Each time, the buffer area is filled and sent, rather than one or two bytes. More efficient.
  • ObjectInputStream: object input stream, which is used to provide persistent storage of basic data or objects. That is, objects can be transferred directly (used in deserialization).
  • DataInputStream: data input stream, which is used to decorate other input streams.

3.3.2 methods in InputStream ๐Ÿ

All subsequent inherited subclasses have these methods. The basic byte input stream needs the read() method to read the file and use the close() method to close the resource.

3.3.3. FileInputStream๐ŸŽ

The use of FileInputStream is basically similar to FileOutputStream.

1. Construction method
  • Public FileInputStream (File): create a FileInputStream by opening the connection with the actual File, which is named by the File object File in the File system.
  • public FileInputStream(String name): create a FileInputStream by opening the connection with the actual file, which is named by the pathname in the file system.

This time, let's take a look at the file information before construction:

public class FileInputStreamTest {
    public static void main(String[] args) throws FileNotFoundException {
        //public FileInputStream(File file)
        //Create a stream object using a File object
        File file = new File("e:\\demo\\b.txt");
        FileInputStream fis = new FileInputStream(file);

        //public FileInputStream(String name)
        // Create a stream object with a file name
        FileInputStream fis2 = new FileInputStream("e:\\demo\\c.txt");
    }
}

Execute the procedure, result:

Exception in thread "main" java.io.FileNotFoundException: e:\demo\c.txt (The system cannot find the specified file.)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.<init>(FileInputStream.java:138)
	at java.io.FileInputStream.<init>(FileInputStream.java:93)
	at com.it.test3.FileInputStreamTest.main(FileInputStreamTest.java:16) 
    The 16 line error here is: FileInputStream fis2 = new FileInputStream("e:\\demo\\c.txt");

be careful ๐Ÿฅ:

  • Different from the output stream, FileInputStream will report an error if the incoming path is empty, while FileOutputStream will create a file.
  • The input stream object created by FileInputStream will not be emptied. It is well understood that the input stream is originally a stream created by reading the file information. If it is empty, what else can I read? Is it lonely.
2. Read data

Since we want to create a byte input stream, isn't it just to read data? Otherwise, what's the use of creating it? Let's see how to use it:

  1. public int read(): one byte of data can be read at a time. The read type is int. when reading to the end of the file, there is no data, and - 1 is returned.

    public class ReadTest {
        public static void main(String[] args) throws IOException {
            // Create a stream object with a file name
            FileInputStream fis = new FileInputStream("e:\\demo\\b.txt");
    
            //int read(): read one byte at a time
            int read = fis.read();
            System.out.println(read);
            System.out.println((char) read);
            
            fis.close();
        }
    }
    

    Output result:

    104
    h
    

    We store hello in b.txt. According to the result read from the input stream, the returned type is int, so we need to forcibly convert it to char character type and return the original file information.

    However, if such a byte is read slowly every time, isn't it troublesome? If the repetition is very high, we can consider optimizing it by loop, but now we don't know what the condition is for the end of the loop? Let's test. What's the result after reading?

    public class ReadTest2 {
        public static void main(String[] args) throws IOException {
            // Create a stream object with a file name
            FileInputStream fis = new FileInputStream("e:\\demo\\b.txt");
    
            //int read(): read one byte at a time
            int read = fis.read();
            System.out.print(read);
            System.out.println(" : "+(char) read);
    
            read = fis.read();
            System.out.print(read);
            System.out.println(" : "+(char) read);
    
            read = fis.read();
            System.out.print(read);
            System.out.println(" : "+(char) read);
    
            read = fis.read();
            System.out.print(read);
            System.out.println(" : "+(char) read);
    
            read = fis.read();
            System.out.print(read);
            System.out.println(" : "+(char) read);
    
            //b.txt, we know that hello can be read five times. What about the sixth time?
            read = fis.read();
            System.out.print(read);
            System.out.println(" : "+(char) read);
    
            fis.close();
        }
    }
    

    Program running results:

    104 : h
    101 : e
    108 : l
    108 : l
    111 : o
    -1 : 
    

    It can be found that if no data is read and the final result is - 1, do we know the condition for the end of the cycle? If no data is read, it returns - 1.

    Let's use cycle improvement:

    public class ReadTest3 {
        public static void main(String[] args) throws IOException {
            // Create a stream object with a file name
            FileInputStream fis = new FileInputStream("e:\\demo\\b.txt");
            // Define variables and save data
            int b;
            // Cyclic reading
            while ((b = fis.read())!=-1) {
                System.out.println((char)b);
            }
            // close resource
            fis.close();
        }
    }
    

    Program running results:

    h
    e
    l
    l
    o
    

    There are several points to note when using input streams:

    • Although a byte is read, it is automatically promoted to type int. Strong return character is required.
    • Like the output stream, after the operation of the input stream is completed, the system resources must be released and the close() method must be called
  2. public int read(byte b []): each time the length of b is read into the array, the number of valid bytes read is returned, and - 1 is returned when the end is read.

    public class ReadTest4 {
        public static void main(String[] args) throws IOException {
            // Create a stream object with a file name
            // b.txt:
            FileInputStream fis = new FileInputStream("e:\\demo\\b.txt");
    
            //public int read(byte b[])
            byte[] b = new byte[3];
            int len = fis.read(b);
            System.out.println(len);// You can see that the reading is the actual length
            System.out.println(new String(b));
    
            len = fis.read(b);
            System.out.println(len);// You can see that the reading is the actual length
            System.out.println(new String(b));
    
            //At this point, it has been read. See if it is the same as reading one. It reads - 1.
            len = fis.read(b);
            System.out.println(len);// You can see that the reading is the actual length
    
            // close resource
            fis.close();
        }
    }
    

    The implementation results are:

    3
    hel
    2
    lol
    -1
    

    Can be found ๐Ÿ‘€:

    • If the actual length is - 1, it indicates that the actual length is not read. This can be used for loop optimization.

    • And we know system out. Println: every time the string is printed out, it will wrap the line, which may confuse our acquisition. Because the characters we read may be on one line, we have to replace them with system out. print.

    • len gets the actual data length. The first time it gets 3, it gets hel, and the second time it gets 2. It's really good, but according to the truth, shouldn't we get lo? How can it be lol? Is this prompting me to hit lol? Hey hey! Do you think I want to like playing games? And it's a man like me who often kills five people and often Cary, a man who ranks as the king. I won't release my achievements here for fear of scaring you. And I don't fight now. If I fight, it may be the next UZI, the shy.

 All right, all right, we'll get to the point. Let's see why we hit it in the end<font color=#ff1493>`lol`</font>What, not<font color=#ff1493>`lo`</font>. 

After knowing the above steps, we carry out cycle optimization and modify the previous problems.

public class ReadTest5 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("e:\\demo\\b.txt");

        byte[] b = new byte[3];
        int len;
        while((len = fis.read(b)) != -1) {
            System.out.print(new String(b, 0, len));//In this way, the actual characters can also be returned
        }

        // close resource
        fis.close();
    }
}

The result of executing the procedure is:
hello

You can see that the hello is perfectly printed on the console, and it will not wrap and reproduce perfectly every time it is read.

Summary ๐Ÿ‘€:

In the development, we use array reading to read multiple bytes each time, which reduces the number of IO operations between systems and improves the efficiency of reading and writing.

3.4 byte stream exercise: image copy ๐Ÿ

Now that we have learned the output stream and input stream of bytes, why don't we take a concrete action:

First, let's explain the principle of wave replication, just like the right-click replication of a computer:

Before copying, first look at the file information to avoid you saying I secretly right-click to copy it.

Follow me and copy pictures in Java. You will find it very simple. So Easy.

public class CopyTest {
    public static void main(String[] args) throws IOException {
        // 1. Create input and output stream objects.
        // 1.1 specify the path of the file to be read.
        FileInputStream fis = new FileInputStream("e:\\demo\\Polaris.jpg");
        // 1.2 specify the path of the destination file.
        FileOutputStream fos = new FileOutputStream("e:\\demoCopy\\Polaris.jpg");

        // 2. Read and write data
        // 2.1 define byte array
        byte[] b = new byte[1024];
        int len;
        // 2.2 cyclic reading and fetching data
        while ((len = fis.read(b))!=-1) {
            // 2.3 write out the obtained byte data
            fos.write(b, 0 , len);
        }

        // 3. Close all resources
        fos.close();
        fis.close();
    }
}

After the program runs, you will see that it will be completed soon. Then check the file and find the copied Polaris jpg is completely lying there.

๐Ÿ˜š Do you want to see the little sister of Polaris? I don't know if you still remember the little sister of Polaris. It's really wonderful, really awsl. For this reason, I specially finished the whole play of talent many years ago. I saw the aurora produced by Polaris and food together. It's really Interesting. The aurora is produced by the flow of charged particles from the sun into the earth's magnetic field.
Hey, hey, you'd better sneak a look at the good things yourself ๐Ÿ˜›๏ผŒ Ha ha, I'd better lie in my folder silently.

4. Character stream ๐Ÿต

Character input / output stream has the same function as byte input / output stream, but the way of transmitting data is different. Byte stream transmits data in bytes, which can make any type of data, such as text, audio, video, picture, etc. Character stream transfers data in character units, and only text type data can be transferred. The advantage of using character I / O stream is that there will be no garbled code when reading Chinese, but this can not be guaranteed when using byte I / O stream. Because a Chinese character may occupy multiple bytes of storage.

What specific problems will happen? Let's have a look. Is there a way to solve them,

public class CharaterTest {
    public static void main(String[] args) throws IOException {
        //FileInputStream is the character input stream of the operation file
        FileInputStream fis = new FileInputStream("E:\\demo\\testTxt.txt");

        int len;
        while ((len = fis.read()) != -1) {
            System.out.print((char) len);
        }

        fis.close();
    }
}

Program running results: 
helloยฑยฑยผยซรร‡รรฒร„รฃยทยขยณรถรŠร“ร†ยตรร„รŒรฌ

This... What are they? I guess you must be wondering if I cheated you. Did I write that on purpose? Of course, it's not. A person like me who is kind, pure and simple and integrates excellent quality will pit you? Let's take a look at my file information.

Because when the byte stream reads Chinese characters, it may not display complete characters, because a Chinese character occupies multiple bytes of storage. But I can't use byte stream to read. What else can I do?

There must be some methods, but it is not particularly convenient for reading Chinese, and we also learn the character stream later. This is particularly convenient for reading Chinese. For this kind of plain text, the first choice is the character stream.

Let's see how to solve it first

public class CharaterTest2 {
    public static void main(String[] args) throws IOException {
        //FileInputStream is the character input stream of the operation file
        FileInputStream fis = new FileInputStream("E:\\demo\\testTxt.txt");

        byte[] b = new byte[1024];
        int len = 0;
        while ((len = fis.read(b)) != -1){
            System.out.print(new String(b, 0, len));
        }

        fis.close();
    }
}

Program running results:
    hello Polaris sends you a video chat

You can read it. You said that if the goddess suddenly sent a message to find you for video chat, but your computer or mobile phone displays a pile of random codes, does your head have a pile of question marks.

Maybe you're still thinking about what the goddess sends and whether she's scolding you. But maybe you missed the chance to have a goddess, so learn Java well.

Back to the point, why can String be used to display normally? Don't worry, let me show you.

public String(byte bytes[], int offset, int length) {
    checkBounds(bytes, offset, length);
    this.value = StringCoding.decode(bytes, offset, length);
}

static char[] decode(byte[] ba, int off, int len) {
    ....  
}

You can see the construction method of String. It has the function of decode. The default is utf-8, which is also the default encoding format. If you use the construction method of String, it means that your text may not be in utf-8 format, but may be encoded in GBK or ANSI format. Later, we will explain in detail how to solve the problem of encoding format. Now you can do this first:

It can be considered as follows: character stream = byte stream + encoding table.

4.1 parent class of character input stream (Reader) ๐Ÿถ

Reader is the parent class of all input character streams. It is an abstract class. The main function is to read character information into memory. It defines the basic common function method of character input stream.

4.1.1 architecture ๐Ÿพ

  • InputStreamReader is a bridge between byte stream and character stream. It reads bytes and decodes them into characters using the specified character set.
  • FileReader is a convenient class for reading character files. The system default character encoding and default byte buffer are used during construction.
  • BufferedReader character buffer stream reads and writes through the buffer to reduce the number of system IO, so as to improve the efficiency of reading and writing.
  • FilterReader is the parent class of all custom concrete decoration flows.

4.1.2 methods in reader ๐Ÿท

After learning byte stream, we can find that the input stream in IO stream is the same, with read(). The subclasses inherited from the character input stream all have these methods. You need the read() method to read the file and use the close() method to close the resources.

4.1.3 FileReader๐Ÿธ

1. Construction method
  • Public FileReader (File): create a new FileReader and give the File object to be read.

  • public FileReader(String fileName): create a new FileReader and give the name of the file to be read.

    Create code demo:

    public class FileReaderTest {
        public static void main(String[] args) throws FileNotFoundException {
    
            // Create a stream object using a File object
            File file = new File("e:\\demo\\a.txt");
            FileReader fr = new FileReader(file);
    
            // Create a stream object with a file name
            FileReader fr2 = new FileReader("e:\\demo\\b.txt");
            
            //FileReader fr3 = new FileReader("e:\\demo\\c.txt");
            //Similarly, if the file cannot be read, an exception will be reported,
            //Exception in thread "main" java.io.FileNotFoundException: e:\demo\c.txt (the system cannot find the specified file.)
        }
    }
    

    It can be seen that the creation method of byte stream is basically the same. If the file cannot be read, an exception will be reported.

2. Read character data

Character stream is used to read text files. Next, let's test:

  1. public int read(): the data can be read one character at a time, promoted to int type, read to the end of the file, and return - 1. It can be tested that, like the byte stream, if no data is read, it will return - 1. Direct use of cyclic reading:

    public class ReaderTest {
        public static void main(String[] args) throws IOException {
            // Create a stream object with a file name
            FileReader fr = new FileReader("e:\\demo\\testTxt.txt");
            // Define variables and save data
            int ch = 0;
            // Cyclic reading
            //public int read()
            while ((ch = fr.read())!=-1) {
                System.out.print((char) ch);
            }
            // close resource
            fr.close();
        }
    }
    
    Program execution results:
       hello Polaris sends you a video chat
    

    be careful:

    • As here, the read value is still int type, which needs to be forcibly converted to character type. Can be displayed as the information of the original file.
    • As before, resources must be closed.
  2. public int read(char cbuf []): each time the length of b is read into the array, it returns the number of valid characters read. When it is read to the end, it returns - 1. Direct use loop demonstration:

    public class ReaderTest2 {
        public static void main(String[] args) throws IOException {
            // Create a stream object with a file name
            FileReader fr = new FileReader("e:\\demo\\testTxt.txt");
            // Define variables and save the number of valid characters
            int len = 0;
            // Defines a character array as a container for character data
            char[] cbuf = new char[2];
            // Cyclic reading
            //public int read(char cbuf[])
            while ((len = fr.read(cbuf)) != -1) {
                System.out.println(new String(cbuf));
            }
            // close resource
            fr.close();
        }
    }
    
    Program execution results:
    arctic
     Star direction
     Your hair
     Out of sight
     Frequent chat
     Chat
    

    It can be seen that it still has one more character, which is the same problem as the byte input stream. Let's improve it by obtaining valid characters:

    public class ReaderTest3 {
        public static void main(String[] args) throws IOException {
            // Create a stream object with a file name
            FileReader fr = new FileReader("e:\\demo\\testTxt.txt");
            // Define variables and save the number of valid characters
            int len = 0;
            // Defines a character array as a container for character data
            char[] cbuf = new char[2];
            // Cyclic reading
            //public int read(char cbuf[])
            while ((len = fr.read(cbuf)) != -1) {
                System.out.println(new String(cbuf, 0, len));
            }
            // close resource
            fr.close();
        }
    }
    
    Program execution results:
    arctic
     Star direction
     Your hair
     Out of sight
     Frequent chat
     day
    

    Summary:

    We found that in fact, we have used most methods in byte stream, and they are basically the same. For plain text, character stream is preferred, while in other cases, byte stream can only be used.

4.2 parent class of character output stream (Writer) ๐Ÿน

Writer is the parent class of all output character streams. It is an abstract class. The main function is to write out the specified character information to the destination. It defines the basic common function method of character output stream.

4.2.1 architecture ๐Ÿบ

  • OutputStreamWriter is a bridge between byte stream and character stream.
  • FilterWriter is the parent class of all custom concrete decoration flows.
  • BufferedWriter character buffer stream reads and writes through the buffer to reduce the number of system IO, so as to improve the efficiency of reading and writing.
  • FileWriter is a convenient class for writing characters to files. The system default character encoding and default byte buffer are used during construction.

4.2.2 methods in writer ๐Ÿป

The usage of byte input stream is completely similar to that of byte input stream. All subclasses inherited by input stream have these methods. writer() method is required to read the file and close() method is used to close the resource.

4.2.3 FileWriter๐Ÿฅ‚

1. Construction method ๐Ÿฅƒ
  • Public FileWriter (File): create a new FileWriter and give the File object to be read.
  • Public FileWriter (file, Boolean append): create a new FileWriter to append data.
  • public FileWriter(String fileName): create a new FileWriter and give the name of the file to be read.
  • public FileWriter(String fileName, boolean append): create a new FileWriter to append data.

The demonstration is as follows:

public class WriterTest {
    public static void main(String[] args) throws IOException {
        //public FileWriter(File file)
        // Create a stream object using a File object
        File file = new File("e:\\demo\\bjx.txt");
        FileWriter fw = new FileWriter(file);


        //public FileWriter(String fileName)
        // Create a stream object with a file name
        FileWriter fw2 = new FileWriter("e:\\demo\\bjx.txt");
    }
}

It can be found that after the program runs, bjx is automatically generated for us in the file Txt file. Same as byte output stream.

The construction method of additional data will not be demonstrated with you. It has also been specially demonstrated above. Hey hey, don't say I'm lazy, because I believe you learned the byte output stream above. You must understand it here, right. Everyone is so smart and talented to learn Java. You can understand it at all.

2. Write data ๐Ÿฅค

Now that the FileWriter object can be created, let's write data in specific practice.

  1. public void write(int c): one character data can be written out at a time.

    public class WriterTest2 {
        public static void main(String[] args) throws IOException {
            // Create a stream object with a file name
            FileWriter fw = new FileWriter("e:\\demo\\bjx.txt");
    
            // Write data
            fw.write(97);//Stored in the file should be: a
            fw.write(26666);//Stored in the file should be:
    
            /*
            [Special note: unlike the byte output stream FileOutputStream.
          	 If the resource is not closed, the data is only saved to the buffer, not to the file.
            */
            //fw.close();
        }
    }
    

    After the program runs, you can see if I don't comment out FW Close () can be saved to a file if there is a closed resource, but if there is no closed resource, it will not be saved to a file. Why?

    • One character = two bytes, while the basic unit of data storage in text is bytes. Can the byte output stream be written in directly, while the character stream cannot be stored directly.

    • The character stream is stored through the buffer. If it is not used, the contents of the buffer cannot be saved to the file.

      You can click in the source code step by step through the write() method, and you can find that it is stored in a CharBuffer buffer.

    • Due to the built-in buffer, if the output stream is not closed, characters cannot be written out to the file. Once the stream resource is closed, we can't write data again, so if we want to write data and continue to use the stream, we need the flush() method.

      Looking at the source code, we can find that both the flush() method and the close() method will eventually call writeBytes() in StreamEncoder.

      flush(): flush the buffer, and the stream object can continue to be used.
      close(): flush the buffer first, and then notify the system to release resources. The stream object can no longer be used.

    Finally, it can be improved to:

    public class WriterTest3 {
        public static void main(String[] args) throws IOException {
            // Create a stream object with a file name
            FileWriter fw = new FileWriter("e:\\demo\\bjx.txt");
    
            // Write data
            //public void write(String str)
            fw.write("Polaris");
            //fw.write('call me ')// Characters cannot be written more, while strings can
            fw.flush();
            fw.write("Call me");
            fw.flush();//Generally, the lower buffer is flushed every time one is written.
            // If you write at the end, if there are exceptions and other errors in the process, did you write it?
            fw.write("Video chat");
            fw.flush();
    
            fw.close();//Even if I comment it out, there is data added
            //fw.write("can you succeed")// When we want to execute here, we will [report an error] Java io. IOException: Stream closed
            //fw.close();
        }
    }
    

    It can be found that:

    • We can write data to the file through the flush() method.
    • Even if the flush() method writes out the data, the close() method must be called at the end of the operation to release the system resources.
  2. puiblic write(char[] cbuf) and public write(char[] cbuf, int off, int len): the data in the character array can be written out each time. The usage of these two functions is similar to that of byte output stream. Let's have a direct demonstration:

    public class WriterTest4 {
        public static void main(String[] args) throws IOException {
            // Create a stream object with a file name
            FileWriter fw = new FileWriter("e:\\demo\\bjx.txt");
    
            // Convert string to byte array
            char[] chars = "Polaris".toCharArray();
    
            // Write out character array
            //puiblic write(char[] cbuf)
            fw.write(chars); // Polaris
            fw.flush();
    
            //Write 2 bytes starting from index 0
            //public write(char[] cbuf, int off, int len)
            fw.write(chars,0,2);//arctic
            fw.flush();
    
            fw.close();
        }
    }
    
    After the program is executed, bjx.txt The file information is:
    Polaris North Pole
    
3. Line feed ๐Ÿงƒ

Since we can realize the function of line feed in byte output stream, can we use character stream? Of course, the answer is the same as the byte output stream. Take a look:

public class WriterTest5 {
    public static void main(String[] args) throws IOException {
        // Create a stream object with a file name
        FileWriter fw = new FileWriter("e:\\demo\\bjx.txt");

        fw.write("Polaris is called");
        fw.flush();
        // Write line breaks
        fw.write("\r\n");
        fw.flush();
        fw.write("I watch the meteor shower together");
        fw.flush();

        fw.close();
    }
}

After the program is executed, bjx.txt The file information is:
Polaris is called
 I watch the meteor shower together

4.3 copy text cases ๐Ÿง‰

The principle of replication has been explained in the byte stream. Now go directly to the code to show you how to:

public class CopyTxtTest {
    public static void main(String[] args) throws IOException {
        // 1. Create input and output stream objects.
        // 1.1 specify the path of the file to be read.
        FileReader fr = new FileReader("E:\\demo\\youth.txt");
        // 1.2 specify the path of the destination file.
        FileWriter fw = new FileWriter("E:\\demoCopy\\youth.txt");

        // 2. Read and write data
        // 2.1 defining character arrays
        char[] chs = new char[1024];
        int len;
        // 2.2 cyclic reading and fetching data
        while ((len = fr.read(chs)) != -1) {
            // 2.3 write out the obtained byte data
            fw.write(chs, 0, len);
            fw.flush();
        }

        // 3. Close all resources
        fw.close();
        fr.close();

    }
}

After the program is executed, look at the information in the following file:

4.4 summary ๐ŸงŠ

Character stream can only operate text files, not pictures, videos and other non text files. When we simply read or write text files, we can use character stream to operate text files more efficiently, while in other cases, we can use byte stream.

  • The difference between the two:
    • The reading and writing units are different: the byte stream is in bytes (8bit) and the character stream is in characters. The characters are mapped according to the code table, and multiple bytes may be read at a time.
    • Different processing objects: byte stream can process all types of data (such as pictures, avi, etc.), while character stream can only process character type data.

๐ŸŒธ summary

I believe all of you have a certain understanding of some basic knowledge and use of IO streams. Wait for the next chapter of advanced streams such as buffer streams (commonly known as efficient streams)! Of course, there are a lot of streams waiting to be seen next time! Pass by, have a look, and promise not to suffer losses!!!

Let's cheer together! I am not talented. If there are any omissions and mistakes, I also welcome criticism and correction in the comments of talent leaders! Of course, if this article is sure to be of little help to you, please also give some praise and collection to the kind and lovely talent leaders. One key three times. Thank you very much!

Learn here, today's world is closed, good night! Although this article is over, I am still there and will never end. I will try to keep writing articles. The future is long. Why should we fear that cars are far away and horses are slow!

Thank you for seeing here! May you live up to your youth and have no regrets!

Topics: Java Back-end