Understand Java IO flows

Java IO stream is the basis of the implementation of input/output, it can facilitate the implementation of data input/output operations, in Java, different input/output sources (keyboard, file, network connection, etc.) abstract into the expression of “flow”.

Classification of streams

1. Byte stream and character stream

  • InputStream
  • Reader
  • OutputStream
  • Writer

The two flow the usage of the basic similar, mainly is the manipulation of data, different byte stream operation is a byte, are those binaries, and characters of the flow will deal with our general to identify these characters text file, byte stream processing 8-bit bytes, characters, stream processing characters of 16 bytes (a character in the Java 2 bytes)

2. Node flow and processing flow

Node flow: A stream used to read and write data, sometimes referred to as a low-level stream because it is less efficient to execute

Processing stream: It encapsulates an existing stream to perform operations such as reading and writing. This is called a high-level stream

So how do we tell if a stream is a node stream or a process stream?

The construction parameter of a node flow is usually a physical address, while the construction parameter of a processing flow is usually an object of the flow

3. Input streams and output streams

Input stream: As the name implies, the ability to read data from a specified object

Output stream: Output data to a specified location

The general direction of the input stream is from the outside to the program

The output stream is from the execution program to the outside of memory

Four base classes for input and output streams:

  • InputStream
  • Reader
  • OutStream
  • Writer

These four classes are abstract and cannot instantiate objects. We usually create subclasses of them, and there are many accessors available in these four classes

Byte stream and character stream

So with that in mind, let’s focus on the use of these two streams

The input stream:

InputStream method:

  • Int read () : Reads a single byte from the input stream, returning the read byte of data
  • Int read (byte[] arr) : Reads data from the input stream and stores it in the byte array arR. Returns the number of bytes read and -1 when the data is read
  • Int read (byte[] arr, int OFF, int length) : Reads length bytes from the input stream into an array of bytes, starting at the off position of the array

Reader methods:

  • Int read () : Reads a single character from the input stream, returning the ASCII encoding of the character
  • Int read (char[] arr) : Reads data from the input stream into the ARR character array
  • Int read (char[] arr, int off, int length) : Reads the length character from the input stream into the character array, starting with the array subscript off

Example: Read the java.txt file as bytes and print it to the console

// using Java7 features, there is no need to manually close resources
try(FileInputStream fis=new FileInputStream("Java.txt")) {byte[] arr=new byte[1024];
    int hasRead;
    while((hasRead=fis.read(arr))>0){
        System.out.println(new String(arr,0,hasRead)); }}Copy the code

Note: there is sometimes a problem here, when we sometimes read incomplete encoding, that is, the byte of a character is read twice, there may be a garble problem, when printing, if simply copying the text is no problem.

try(FileReader fr=new FileReader("Java.txt")) {char[] arr=new char[1024];
    int hasRead;
    while((hasRead=fr.read(arr))>0){
        System.out.println(new String(arr,0,hasRead)); }}Copy the code
The output stream:

The OutputStream method:

  • Void write (int a) : outputs the specified byte to the output stream, where a can be either a byte or a character
  • Void write (byte[]/char[] arr) : Writes data from byte arrays or character arrays to the output stream
  • Void write (byte[]/char[] arr, int OFF, int length) : Write (byte[]/char[] arr, int OFF, int length) to the output stream

Writer’s method:

  • Void write (String String) : Stores the String String to the output stream
  • Void write (String String, int off, int length) : Outputs a String of specified length to the output stream

Example: Copy the contents of the java. TXT file to the java2.txt file

try(
	FileInputStream fis=new FileInputStream("Java.txt");
    FileOutputStream fos=new FileOutputStream("Java2.txt"); {byte[] arr=new byte[1024];
    int hasRead;
    while((hasRead=fis.read(arr))>0){
        fos.write(arr,0,hasRead); }}Copy the code

Normally, we’re dealing with characters in a character stream, or a byte stream, because byte streams are more versatile, and characters are converted from binary

How to use processing streams

Processing flow: Wrapping existing flow objects can improve the efficiency of processing data and make it easier for some data operations

Let’s talk about a very powerful stream called PrintStream, which is essentially a byte stream, which is a processing stream that we use to output data, and if we want to output text, we should wrap the output stream as PrintStream output

1. First we will create an output stream object

2. Create a print stream object, pass in parameters, and wrap the output stream

Example:

try(
	FileOutputStream fos=new FileOutputStream("Java.txt");
    PrintStream ps=new PrintStream(fos);
)
{
    ps.println("Hello, tomorrow.");
    ps.println(new Date());
}
Copy the code

The effect of this code execution is to print the string hello tomorrow and an instance object of the Date class to a java.txt file

Note: When we close the processing stream, the stream it wraps will also close

Transformation flows

Java provides two transformation flows

  • InputStreamReader: Converts a byte input stream into a character input stream
  • OutputStreamReader: Converts a byte output stream into a character output stream

We’ll do one thing: in Java, System.in stands for standard input, the keyboard, and System.out stands for standard output, the console

Sometimes we can turn a byte input stream into a character input stream

Example: In this example we convert system. in to a character input stream, and then use BufferedReader to process the stream wrapper to speed up efficiency

try(
	InputStreamReader isr=new InputStreamReader(System.in);
    BufferedReader br=new BufferedReader(isr);
)
{
    String line=null;
    while((line=br.readLine())! =null) {if("exit".equals(line)){
            break;
        }else{ System.out.println(line); }}}Copy the code

This code first converts the standard input stream into a character input stream, then wraps it in a buffered stream,

The buffered stream has a readLine method that reads an entire line, in this case from the keyboard, to loop through

Redirect to the standard I/O stream

With Java we often read what we want from the keyboard via system.in or output data to the console using system.out, but sometimes we want to read from text, or save the data to text instead of printing it to the console. What do we do?

Class methods are provided in the System class:

  • Void setIn (InputStream in) : redirect to the standard InputStream and get data from the stream specified by in instead of the keyboard
  • Void setOut (PrintStream out) : Repoints to the standard output stream and prints the output to the out output stream instead of the console

Example:

try(
	PrintStream ps=new PrintStream(new FileOutputStream("Java.txt")); { System.setOut(ps); System.out.println("Hello tomorrow.");
    System.out.println(new Date());
}
Copy the code

In this code, the standard output of the System refers to the stream specified by PrintStream, so the output of subsequent system.out.println operations will enter the text instead of being displayed on the console. You can also write data to text using ps.println()

Example:

try(
	FileInputStream fis=new FileInputStream("Java.txt"); { System.setIn(fis); Scanner sc=new Scanner(System.in);
    sc.useDelimiter("\n");
    while(sc.hasNext()){ System.out.println(sc.next()); }}Copy the code

This code respecifies standard input, not from the keyboard, but from the text, using a loop to constantly determine if the text has any data, and if so, to read

sc.useDelimiter("\n");
Copy the code

This means that the content is delimited by carriage return, otherwise it is delimited by space by default

Powerful stream: RandomAccessFile stream

The RandomAccessFile stream is a rich Java stream that can read and write data arbitrarily, which supports “random access”.

We can use this stream when we don’t need to read all of the data, but only part of it

But it has a disadvantage, it can only manipulate text files, not other streams

Since it can be read arbitrarily, it means that there is an internal pointer to the current file location

  • Long getFilePointer () : Returns the current position of the file pointer
  • Void seek (long pos) : moves the file pointer to pos

It has several read and write modes:

  1. R: Open the file in read-only mode
  2. Rw: Opens the file in both read and write mode, if not created automatically

Example: Read part of the data in the java. TXT file

try(
	RandomAccessFile raf=new RandomAccessFile("Java.txt"."r"); { raf.seek(100);
    byte[] arr=new byte[1024];
    int hasRead;
    while((has=raf.read(arr))>0){
        System.out.println(new String(arr,0,hasRead)); }}Copy the code

It has all the methods for basic input and output streams.

Example: Append files to files

try(
	RandomAccessFile raf=new RandomAccessFile("Java.txt"); { raf.seek(raf.length()); raf.write("Append text");
}
Copy the code

Point to the end of the file and continue writing data

So how do we implement insert data? When we change the pointer to the specified position and write data, the following data will be overwritten, so we need to save this part of the file and then restore

File tempFile=File.createTempFile("temp.txt".null);
tempFile.deleteOnExit();
try(
	RandomAccessFile raf=new RandomAccessFile(fileName,"rw");
    FileInputStream fis=new FileInputStream(tempFile);
    FileOutputStream fos=new FileOutputStream(tempFile);
)
{
    raf.seek(pos);
    byte[] arr=new byte[1024];
    int hasRead;
    while((hasRead=raf.read(arr))>0){
        fos.write(arr,0,hasRead);
    }
    raf.seek(pos);
    raf.write(InsertContent.getBytes());// Convert a string to a byte array
    while((hasRead=fis.read(arr))>0){
        raf.write(arr,0,hasRead); }}Copy the code

In the above code we define a temporary file and specify that it will be deleted automatically when the program ends

We first record the text after the insertion position into a temporary file, and then we insert the content we want to insert

We then write the contents of the temporary file back into the file to complete the insert operation

Note:

We can also append files to text in this way:

FileWriter fw=new FileWriter("Java.txt".true);
Copy the code

The last parameter indicates whether to append data