Java Basic Learning 17 IO streams, byte streams, character streams

“This is the 17th day of my participation in the Gwen Challenge in November. See details of the event: The Last Gwen Challenge in 2021”.

About the author

  • The authors introduce

🍓 Blog home page: author’s home page 🍓 Introduction: 🥇, a high quality creator in JAVA field, 🎓, a junior in college, participated in various provincial and national competitions and won a series of honors. 🍓 pay attention to me: pay attention to my learning materials, document download all have, regularly update the article every day, inspirational to do a JAVA senior program ape 👨💻.

IO – byte stream and character stream

The essential difference between a character stream and a byte stream is that only one byte stream is a native operation, while a two-character stream is a processed operation. The only supported data type saved through disk data storage is: bytes. All data on disk must be read to memory before operation. Memory will help us convert bytes into characters. Characters are more suitable for handling Chinese.

Byte operation streams: OutputStream,InputStream;

Character operation streams: Writer,Reader.

However, both byte stream and character stream operations themselves represent resource operations, and all resources are executed in accordance with the following steps. The following uses file operations as an example (read and write operations on files) :

  1. The File object is created from the File
  2. Instantiate our superclass object based on a subclass of byte stream or character stream
  3. Read and write data
  4. Close the stream (clone())

I/O operations are resource processing. All resource processing must be closed after the processing is complete. Otherwise, resources cannot be executed.

Byte OutputStream: OutputStream

Java.io.OutputStream the main function of java.io.OutputStream is to output byte data.

public abstract class OutputStream extends Object implements Closeable.Flushable
Copy the code

OutputStream {Closeable,Flushable}} OutputStream {Closeable,Flushable}}

Closeable: Flushable:
public interface Closeable

extends AutoCloseable{

public void close() throws IOException;

}
public interface Closeable{

public void flush() throws IOException;

}

Once the OutputStream class instantiates the object, we must output it. We define three methods in the OutputStream class:

Output single byte array data: public abstract void write(int B) throws IOException

Outputs a group of byte array data: public void write(byte[] b) throws IOException

Outputs partial byte array data: public void write(byte[] b,int off,int len) throws IOException

Tip: Inherit the AutoCloseable interface for Closeable

A new interface for AuotCloseable was added in JDK1.7, but the definition for this interface is exactly the same as for Closeable. It is possible that on some other classes there is an automatic closing function, Closeable is manually closed, AutoCloseable is automatically closed.

Flush () and close() methods are defined directly in the OutputStream class from the earliest days, so there is little concern about the parent interface.

For the OutputStream class, it is found that it defines an abstract class. According to the principle of using abstract classes, if you want to instantiate the parent class, you need to use the subclass, and you need to define the abstract subclass. Now, if you want to perform file operations, You can do this using a FileOutputStream subclass. If according to the object-oriented development principle, the subclass should instantiate the object for the abstract class, and then call the method defined in the parent class, and the concrete implementation is to find the subclass that instantiates the parent class to complete, that is, in the whole operation, the user is most concerned about only the constructor of the subclass:

Instantiate FileOutputStream(new data) : public FileOutputStream([File File) throws FileNotFoundException

Instantiate FileOutputStream(append data) : public FileOutputStream(File File, Boolean Append) throws FileNotFoundException

Implements output of file contents

package com.day14.demo;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class OutputDemo {
	public static void main(String[] args) throws Exception {
		//1. Define the file path
		File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt");
		if(! file.getParentFile().exists()){// The parent path does not exist
			file.getParentFile().mkdirs();// Create a parent directory
		}
		//2. Data to be output
		String str = "Hello,zsr!!!!";
		//3. Instantiate the object
		FileOutputStream stream = new FileOutputStream(file);
		//4. Write content to stream
		stream.write(str.getBytes());// Output data, to output the data into a byte array output
		/ / 5. Close the flowstream.close(); }}Copy the code

By default, FileOutputStream is overwritten. If you do not want to overwrite the document, you can change FileOutputStream to FileOutputStream

FileOutputStream stream = new FileOutputStream(file,true);
Copy the code

If a line break is required for writing, use \r\n for line breaks.

Byte InputStream: InputStream

If you now want to read data from a specified data source, use InputStream, which is defined as follows:

public abstract class InputStreamextends Objectimplements Closeable
Copy the code

InputStream implements only the Closeable interface

Three methods for reading data are defined in InputStream:

Read a single byte: public Abstract int read() throws IOException

Note: Each execution of the read() method reads the specified data from a data source, and returns -1 if it is now found that the end has been read.

Read multiple bytes: public int read(byte[] b) throws IOException

Note: If the number of bytes being read is smaller than the array, the return value of the read() method int returns the number of bytes; If the byte array is smaller than the read length, then the length is returned. Int returns -1 if the data has been read.

Public int read(byte[] b,int off,int len) throws IOException

Only part of the passed array is read at a time. If the read is full, the length is returned. If not full, returns the number of reads; If there is no data at the end of the read, -1 is returned

Since InputStream is an abstract class, it must have a subclass in order to use it. Now that we are reading from a file, we must use a FileInputStream subclass to operate, just as we use the OutputStream class.

FileInputStream Class constructor: public FileInputStream(File File) throws FileNotFoundException

Read file information

package com.day14.demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;


public class InputDemo {
	public static void main(String[] args) throws Exception {
		File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt");
		if(! file.exists()){ System.out.println("Specified file does not exist!!");
		}else{
			FileInputStream is = new FileInputStream(file);
			byte[] result = new byte[1024];
			int length = is.read(result);
			System.out.println("Read:" + new String(result,0,length)); }}}Copy the code

Character output stream: Writer

The Writer class is also a special operation class for data output, which is friendly to Chinese data. This class defines:

public abstract class Writer
extends Object
implements Appendable.Closeable.Flushable
Copy the code

The Writer () methods defined in the Writer class are all character data oriented, but only one of these methods is concerned with:

Outputs a String: public void write(String STR) throws IOException

Always use FileWriter subclasses if you want to manipulate files.

package com.day14.demo;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class WriterDemo {
	public static void main(String[] args) throws IOException {
		//1. Define the file path
		File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt");
		if(! file.getParentFile().exists()){// The parent path does not exist
			file.getParentFile().mkdirs();// Create a parent directory
		}
		//2. Data to be output
		String str = "I'm taking a course in Java !!!! \r\n";
		// If you want to override the content, just use true
		//FileWriter out = new FileWriter(file,true);
		FileWriter out = newFileWriter(file); out.write(str); out.close(); }}Copy the code

Character input stream: Reader

Reader is an operation class that reads character data.

public abstract class Reader
extends Object
implements Readable.Closeable
Copy the code

The Writer class has a method for writing a string, but the Reader class does not define such a method, just three methods for reading a string. Why is that?

Because when OutputStream is used to output data, the output size of the program must be the size of the data that the program can withstand. Therefore, if InputStream is used to read data, the data that may be read is very large. If all data is read at one time, there will be problems.

Reader is still abstract, so if you read from a file, you still use the FileReader class

package com.day14.demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class ReadDemo {
	public static void main(String[] args) throws IOException {
		File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt");
		if(! file.exists()){ System.out.println("Specified file does not exist!!");
		}else{
			FileReader reader = new FileReader(file);
			char[] result = new char[1024];
			int length = reader.read(result);
			System.out.println("Read:" + new String(result,0,length)); }}}Copy the code

The advantage of characters over bytes is that string data is supported only in the Writer() class, so character streams do not operate as equivalents compared to byte streams.

A byte stream is distinguished from a character stream

Through the analysis of our system, we can find that the code operation of byte stream and character stream is not very different. If we use it in practice, we give priority to byte stream and only consider using character stream when we use Chinese, because all characters need to be processed by memory buffer.

Since reading data requires caching, so does writing data. If the character stream is not refreshed, our content may be in the cache, so we must force a refresh to get the complete data content.

package com.day14.demo;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class WriterDemo {
	public static void main(String[] args) throws IOException {
		//1. Define the file path
		File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt");
		if(! file.getParentFile().exists()){// The parent path does not exist
			file.getParentFile().mkdirs();// Create a parent directory
		}
		//2. Data to be output
		String str = "I'm taking a course in Java !!!! \r\n";
		// If you want to override the content, just use true
		//FileWriter out = new FileWriter(file,true);
		FileWriter out = newFileWriter(file); out.write(str); out.flush(); }}Copy the code

In future I/O processing, if processing pictures, music, text can use byte stream, only when processing Chinese will use character stream.

Transformation flows

There are now byte streams and character streams for IO operations, and there are two classes of operations that can be converted between these two operations:

Change byte OutputStream to character OutputStream (OutputStream->Writer) — OutputStreamWriter;

Change a byte InputStream to a character InputStream (InputStream->Reader) — InputStreaReader.

OutputStreamWriter InputStreamReader
public class OutputStreamWriter

extends Writer
public class InputStreamReader

extends Reader
public OutputStreamWriter(OutputStream out) public InputStreamReader(InputStream in)

It is clear from the above inheritance structure and constructor that since OutputStreamWriter is a subclass of Writer, OutputStreamWriter must be able to receive objects by upcasting them through the Writer class. In the meantime, the constructor of the OutputStreamWriter class can receive an OutputStream, thus completing the transformation.

Turns a byte output stream into a character output stream

package com.day14.demo;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;

public class OutWriterDemo {
	public static void main(String[] args) throws Exception {
		//1. Define the file path
		File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt");
		if(! file.getParentFile().exists()){// The parent path does not exist
			file.getParentFile().mkdirs();// Create a parent directory
		}
		//2. Data to be output
		String str = "Hello,world!!!!";
		//3. Instantiate the object
		OutputStream stream = new FileOutputStream(file,true);
		//4. Write content to stream
		Writer out = new OutputStreamWriter(stream);
		out.write(str);
		/ / 5. Close the flowout.close(); }}Copy the code

FileInputStream, FileOutputStream, FileReader, and FileWriter can be used for file operations. The following are the inheritance structures of these four classes.

Look at FileInputStream, the FileOutoutStream class’s inheritance structure

FileInputStream FileOutoutStream
java.lang.Object

java.io.InputStream

java.io.FilterInputStream
java.lang.Object

java.io.OutputStream

java.io.FileOutputStream

Look at the inheritance structure of the FileReader, FileWriter class

FileReader FileWrite
java.lang.Object

java.io.Reader

java.io.InputStreamReader

java.io.FileReader
java.lang.Object

java.io.Writer

java.io.OutputStreamWriter

java.io.FileWriter

Through the inheritance relationship above, it can also be found that, in fact, all character data need to be converted, relying on the conversion stream to complete, the real saved or transmitted data can not have characters, all are bytes, and bytes are only the result of processing in the computer.