Java Foundation
Chapter 20 byte stream and character stream
IO overview
What is IO
We can regard data transmission as a kind of data flow. According to the flow direction and based on memory, it is divided into input input and output, that is, the flow to memory is the input flow and the output flow out of memory.
I/O operation in Java mainly refers to the use of Java Input and output the contents under the IO package. Input is also called read data, and output is also called write data.
Classification of IO
According to the flow direction of data, it is divided into input flow and output flow.
- Input stream: a stream that reads data from other devices into memory.
- Output stream: a stream that writes data out of memory to other devices.
The types of pattern data are divided into byte stream and character stream.
- Byte stream: a stream that reads and writes data in bytes.
- Character stream: a stream that reads and writes data in character units.
Flow direction illustration of IO
1.4 top level parent classes
Input stream | Output stream | |
---|---|---|
Byte stream | Byte input stream InputStream | Byte output stream OutputStream |
Character stream | Character input stream Reader | Character output stream Writer |
Byte stream
Everything is a byte
All file data (text, pictures, videos, etc.) are stored in binary numbers, bytes by bytes, and the same is true during transmission. 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.
Byte output stream [OutputStream]
java.io.OutputStream abstract class is a superclass representing all classes of byte output stream, which writes the specified byte information to the destination. It defines the basic common function method of byte output stream.
- public void close(): close this output stream and release any system resources associated with this stream.
- public void flush(): flushes this output stream and forces any buffered output bytes to be written out.
- public void write(byte[] b): writes b.length bytes from the specified byte array to this output stream.
- public void write(byte[] b, int off, int len): writes len bytes from the specified byte array and outputs them to this output stream starting from offset off.
- public abstract void write(int b): outputs the specified bytes to the stream.
tips:
close method, which must be called to release system resources when the operation of the stream is completed.
FileOutputStream class
OutputStream has many subclasses. Let's start with the simplest subclass.
java. io. The fileoutputstream class is a file output stream used to write data out to a file.
Construction method
- public FileOutputStream(File file): creates a File output stream to write to the File represented by the specified File object.
- public FileOutputStream(String name): creates a file output stream and writes it to the file with the specified name.
When you create a stream object, you must pass in a file path. Under 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.
The code is as follows (example):
public class FileOutputStreamConstructor throws IOException { public static void main(String[] args) { // Create a stream object using a File object File file = new File("a.txt"); FileOutputStream fos = new FileOutputStream(file); // Create a stream object with a file name FileOutputStream fos = new FileOutputStream("b.txt"); } }
Write byte data
- Write byte: write(int b) method can write one byte of data at a time. The code usage demonstration:
public class FOSWrite { public static void main(String[] args) throws IOException { // Create a stream object with a file name FileOutputStream fos = new FileOutputStream("fos.txt"); // Write data fos.write(97); // Write the first byte fos.write(98); // Write the second byte fos.write(99); // Write the third byte // close resource fos.close(); } }
Output results:
abc
tips:
- Although the parameter is four bytes of int type, only one byte of information will be reserved.
- After the stream operation is completed, you must release system resources and call the close method.
- Write out byte array: write(byte[] b). You can write out the data in the array each time. The code usage demonstration:
public class FOSWrite { public static void main(String[] args) throws IOException { // Create a stream object with a file name FileOutputStream fos = new FileOutputStream("fos.txt"); // Convert string to byte array byte[] b = "Kamen Rider W".getBytes(); // Write out byte array data fos.write(b); // close resource fos.close(); } }
Output results:
Kamen Rider W
- Write out the byte array of the specified length: write(byte[] b, int off, int len). Each write starts from the off index, len bytes. Code usage demonstration:
public class FOSWrite { public static void main(String[] args) throws IOException { // Create a stream object with a file name FileOutputStream fos = new FileOutputStream("fos.txt"); // Convert string to byte array byte[] b = "abcde".getBytes(); // Write 2 bytes starting from index 2. Index 2 is c, two bytes, that is, cd. fos.write(b,2,2); // close resource fos.close(); } }
Output results:
cd
Data append and continue
After the above demonstration, each time the program runs and creates an output stream object, the data in the target file will be cleared. How to keep the data in the target file and continue to add new data?
- Public fileoutputstream (File, Boolean append): creates a File output stream to write to the File represented by the specified File object.
- public FileOutputStream(String name, boolean append): creates a file output stream and writes it to the file with the specified name.
For these two construction methods, a boolean value needs to be passed in the parameters. true means to append data, and false means to empty the original data. The output stream object created in this way can be used to specify whether to append and continue. The code uses the following demonstration:
public class FOSWrite { public static void main(String[] args) throws IOException { // Create a stream object with a file name FileOutputStream fos = new FileOutputStream("fos.txt",true); // Convert string to byte array byte[] b = "abcde".getBytes(); // Write 2 bytes starting from index 2. Index 2 is c, two bytes, that is, cd. fos.write(b); // close resource fos.close(); } }
Before file operation: cd After file operation: cdabcde
Write line breaks
On Windows systems, the newline symbol is \ r\n. hold
To specify whether to append and continue. The code usage demonstration:
public class FOSWrite { public static void main(String[] args) throws IOException { // Create a stream object with a file name FileOutputStream fos = new FileOutputStream("fos.txt"); // Define byte array byte[] words = {97,98,99,100,101}; // Traversal array for (int i = 0; i < words.length; i++) { // Write a byte fos.write(words[i]); // Write a newline and convert the newline symbol into an array fos.write("\r\n".getBytes()); } // close resource fos.close(); } }
Output results: a b c d e
- 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 systems, there is only newline at the end of each line, that is \ n;
- On the MAC system, the end of each line is enter, that is, \ r. Unified with Linux starting with Mac OS X.
Byte input stream [InputStream]
java.io.InputStream abstract class is a super class representing all classes of byte input stream, which can read byte information into memory. It defines the basic common function method of byte input stream.
- public void close(): close this input stream and release any system resources associated with this stream.
- public abstract int read(): reads the next byte of data from the input stream.
- public int read(byte[] b): read some bytes from the input stream and store them in byte array B.
tips:
close method, which must be called to release system resources when the operation of the stream is completed.
FileInputStream class
java. io. The FileInputStream class is a file input stream that reads bytes from a file.
Construction method
- FileInputStream(File file): create a FileInputStream by opening a connection to the actual file, which is named by the file object file in the file system.
- FileInputStream(String name): create a FileInputStream by opening a connection to the actual file, which is named by the pathname in the file system.
When you create a stream object, you must pass in a file path. If there is no such file in this path, FileNotFoundException will be thrown.
The code is as follows (example):
public class FileInputStreamConstructor throws IOException{ public static void main(String[] args) { // Create a stream object using a File object File file = new File("a.txt"); FileInputStream fos = new FileInputStream(file); // Create a stream object with a file name FileInputStream fos = new FileInputStream("b.txt"); } }
Read byte data
- Read bytes: the read method can read one byte of data at a time, promote it to int type, read it to the end of the file, and return - 1.
There are abcde contents in the read file. The read method is used to read the contents of the file. The code is shown as follows:
public class FISRead { public static void main(String[] args) throws IOException{ // Create a stream object with a file name FileInputStream fis = new FileInputStream("read.txt"); // Read data and return a byte int read = fis.read(); System.out.println((char) read); read = fis.read(); System.out.println((char) read); read = fis.read(); System.out.println((char) read); read = fis.read(); System.out.println((char) read); read = fis.read(); System.out.println((char) read); // Read to the end and return - 1 read = fis.read(); System.out.println( read); // close resource fis.close(); } }
Output results: a b c d e -1
We can improve the reading mode by using the loop. The code usage demonstration:
public class FISRead { public static void main(String[] args) throws IOException{ // Create a stream object with a file name FileInputStream fis = new FileInputStream("read.txt"); // Define variables and save data int b ; // Cyclic reading while ((b = fis.read())!=-1) { System.out.println((char)b); } // close resource fis.close(); } }
Output results: a b c d e
tips:
- Although a byte is read, it is automatically promoted to type int.
- After the stream operation is completed, you must release system resources and call the close method.
- Read using byte array: read(byte[] b). Each time the length of B is read into the array, return the number of valid bytes read. When reading to the end, return - 1. Code usage demonstration:
public class FISRead { public static void main(String[] args) throws IOException{ // Create a stream object with a file name FileInputStream fis = new FileInputStream("read.txt"); // abcde in file // Define variables as valid numbers int len ; // Defines a byte array as a container for byte data byte[] b = new byte[2]; // Cyclic reading while (( len= fis.read(b))!=-1) { // After each reading, the array is changed into a string for printing System.out.println(new String(b)); } // close resource fis.close(); } }
Output results: ab cd ed
The error data d is because only one byte e is read during the last reading. In the array, the last read data has not been completely replaced, so it is necessary to obtain valid bytes through len. The code usage demonstration:
public class FISRead { public static void main(String[] args) throws IOException{ // Create a stream object with a file name FileInputStream fis = new FileInputStream("read.txt"); // abcde in file // Define variables as valid numbers int len ; // Defines a byte array as a container for byte data byte[] b = new byte[2]; // Cyclic reading while (( len= fis.read(b))!=-1) { // After each reading, the valid byte part of the array is changed into a string for printing System.out.println(new String(b,0,len));// len number of valid bytes read each time } // close resource fis.close(); } }
Output results: ab cd e
tips:
Using array reading, multiple bytes are read each time, which reduces the number of IO operations between systems, thus improving the efficiency of reading and writing.
Character stream
There may be a small problem when using byte stream to read text files. When Chinese characters are encountered, complete characters may not be displayed because a Chinese character may occupy multiple bytes of storage. Therefore, Java provides some character stream classes to read and write data in character units, which are specially used to process text files.
Character input stream [Reader]
java. io. The reader abstract class is a superclass that represents all classes used to read character streams. It can read character information into memory. It defines the basic common function method of character input stream.
- public void close(): close the flow and release any system resources associated with the flow.
- public int read(): reads a character from the input stream.
- public int read(char[] cbuf): reads some characters from the input stream and stores them in the character array cbuf.
tips:
Close: flow closing principle: open first and then close, and then open and close first.
FileReader class
java. io. The FileReader class is a convenient class for reading character files. The system default character encoding and default byte buffer are used during construction.
tips:
-
Character encoding: the correspondence rule between bytes and characters. The Chinese code of Windows system is GBK code table by default.
UTF-8 in idea
-
Byte buffer: a byte array used to temporarily store byte data.
Construction method
- FileReader (File): create a new FileReader and give the File object to be read.
- FileReader(String fileName): create a new FileReader and give the name of the file to be read.
When you create a stream object, you must pass in a file path. Similar to FileInputStream.
The code is as follows (example):
public class FileReaderConstructor throws IOException{ public static void main(String[] args) { // Create a stream object using a File object File file = new File("a.txt"); FileReader fr = new FileReader(file); // Create a stream object with a file name FileReader fr = new FileReader("b.txt"); } }
Read character data
- Read character: the read method can read data one character at a time, promote it to int type, read it to the end of the file, return - 1, read it circularly, and demonstrate the use of the code:
public class FRRead { public static void main(String[] args) throws IOException { // Create a stream object with a file name FileReader fr = new FileReader("read.txt");//The content of the file is: masked Knight W // Define variables and save data int b ; // Cyclic reading while ((b = fr.read())!=-1) { System.out.println((char)b); } // close resource fr.close(); } }
Output results: false noodles ride Scholar W
- Read using the character array: read(char[] cbuf). Each time the length of b is read into the array, return the number of valid characters read. When reading to the end, return - 1.
The code is as follows (example):
public class FISRead { public static void main(String[] args) throws IOException { // Create a stream object with a file name FileReader fr = new FileReader("read.txt"); // Define variables and save the number of valid characters int len ; // Defines a character array as a container for character data char[] cbuf = new char[2]; // Cyclic reading while ((len = fr.read(cbuf))!=-1) { System.out.println(new String(cbuf,0,len)); } // close resource fr.close(); } }
Output results: Mask knight W
Character output stream [Writer]
java. io. The writer abstract class is a superclass that represents all classes used to write out the character stream and writes the specified character information to the destination. It defines the basic common function method of byte output stream.
- void write(int c) writes a single character.
- void write(char[] cbuf) writes to the character array.
- abstract void write(char[] cbuf, int off, int len) writes a part of the character array, the start index of the off array, and the number of characters written by Len.
- void write(String str) writes a string.
- void write(String str, int off, int len) writes a part of the string, the start index of the off string, and the number of characters written by Len.
- void flush() flushes the buffer of the stream.
- void close() closes the stream, but first refreshes it.
FileWriter class
java. io. The filewriter class is a convenient class for writing characters to files. The system default character encoding and default byte buffer are used during construction.
Construction method
- FileWriter (File): create a new FileWriter and give the File object to be read.
- FileWriter(String fileName): create a new FileWriter and give the name of the file to be read.
When you create a stream object, you must pass in a file path, similar to FileOutputStream.
The code is as follows (example):
public class FileWriterConstructor { public static void main(String[] args) throws IOException { // Create a stream object using a File object File file = new File("a.txt"); FileWriter fw = new FileWriter(file); // Create a stream object with a file name FileWriter fw = new FileWriter("b.txt"); } }
Basic write data
Write out characters: write(int b) method can write out character data one at a time.
The code is as follows (example):
public class FWWrite { public static void main(String[] args) throws IOException { // Create a stream object with a file name FileWriter fw = new FileWriter("fw.txt"); // Write data fw.write(97); // Write the first character fw.write('b'); // Write the second character fw.write('C'); // Write the third character fw.write(30000); // Write the fourth character. 30000 in the Chinese coding table corresponds to a Chinese character. /* [Note: when closing resources, it is different from FileOutputStream. If it is not closed, the data is only saved to the buffer, not to the file. */ // fw.close(); } }
Output results: abC field
tips:
- Although the parameter is four bytes of int type, only one character of information will be reserved.
- The close method is not called, and the data is only saved to the buffer and not written out to the file.
Close and refresh
Because of the built-in buffer, characters cannot be written out to the file without closing the output stream. However, closed stream objects cannot continue to write data. If we want to write data and continue to use the stream, we need the flush method.
- 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. Stream objects can no longer be used.
The code is as follows (example):
public class FWWrite { public static void main(String[] args) throws IOException { // Create a stream object with a file name FileWriter fw = new FileWriter("fw.txt"); // Write out the data through flush fw.write('brush'); // Write the first character fw.flush(); fw.write('new'); // Continue to write the second character and write successfully fw.flush(); // Write out the data through close fw.write('shut'); // Write the first character fw.close(); fw.write('close'); // Continue to write the second character, [error] java.io.IOException: Stream closed fw.close(); } }
tips: even if the flush method writes out data, the close method must be called at the end of the operation to release system resources.
Write other data
- Write out the character array: write(char[] cbuf) and write(char[] cbuf, int off, int len). You can write out the data in the character array each time. The usage is similar to FileOutputStream.
The code is as follows (example):
public class FWWrite { public static void main(String[] args) throws IOException { // Create a stream object with a file name FileWriter fw = new FileWriter("fw.txt"); // Convert string to byte array char[] chars = "Kamen Rider W".toCharArray(); // Write out character array fw.write(chars); // Masked Knight W // Write 2 bytes starting from index 2. Index 2 is' process', two bytes, that is' program '. fw.write(b,2,2); // knight // close resource fos.close(); } }
- Write out string: write(String str) and write(String str, int off, int len). You can write out the data in the string each time, which is more convenient.
The code is as follows (example):
public class FWWrite { public static void main(String[] args) throws IOException { // Create a stream object with a file name FileWriter fw = new FileWriter("fw.txt"); // character string String msg = "Kamen Rider W"; // Write out character array fw.write(msg); //Masked Knight W // Write 2 bytes starting from index 2. Index 2 is' process', two bytes, that is' program '. fw.write(msg,2,2); // knight // close resource fos.close(); } }
- Continue and line feed: the operation is similar to FileOutputStream.
public class FWWrite { public static void main(String[] args) throws IOException { // Create a stream object with a file name to continue writing data FileWriter fw = new FileWriter("fw.txt",true); // Write out string fw.write("Mask"); // Write line breaks fw.write("\r\n"); // Write out string fw.write("knight W"); // close resource fw.close(); } }
Output results: Mask knight W
tips: character stream. You can only operate on text files, but not on non text files such as pictures and videos.
When we simply read or write text files, we use character stream. In other cases, we use byte stream
Handling of IO exceptions
JDK7 pretreatment
In the previous exercise, we have been throwing exceptions, which cannot be handled in the actual development. It is recommended to use try catch... Finally code block, exception handling part, code usage demonstration:
public class HandleException1 { public static void main(String[] args) { // Declare variable FileWriter fw = null; try { //Create flow object fw = new FileWriter("fw.txt"); // Write data fw.write("Kamen Rider W"); //Masked Knight W } catch (IOException e) { e.printStackTrace(); } finally { try { if (fw != null) { fw.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
Disadvantages of try finally:
If multiple resources are opened at the same time, a nightmare scenario will appear: the more resources are opened, the deeper the nesting in finally.
JDK7 processing (expand knowledge points to understand content)
You can also use the JDK7 optimized try with resource statement, which ensures that each resource is closed at the end of the statement. The so-called resource refers to the object that must be closed after the program is completed.
Format:
try (Create a stream object statement, if more than one,use';'separate) { // Read and write data } catch (IOException e) { e.printStackTrace(); }
Code usage demonstration:
public class HandleException2 { public static void main(String[] args) { // Create flow object try ( FileWriter fw = new FileWriter("fw.txt"); ) { // Write data fw.write("Kamen Rider W"); //Masked Knight W } catch (IOException e) { e.printStackTrace(); } } }
Improvement of JDK9 (expand knowledge points to understand content)
The improvement of try with resource in JDK9 supports a more concise way of introducing objects. The introduced objects can also be close d automatically without manual closing. Let's learn about the format.
Format before improvement:
// final decorated object final Resource resource1 = new Resource("resource1"); // Common object Resource resource2 = new Resource("resource2"); // Import method: create a new variable and save it try (Resource r1 = resource1; Resource r2 = resource2) { // Use object }
Improved format:
// final decorated object final Resource resource1 = new Resource("resource1"); // Common object Resource resource2 = new Resource("resource2"); // Import method: direct import try (resource1; resource2) { // Use object }
After improvement, the code use demonstration:
public class TryDemo { public static void main(String[] args) throws IOException { // Create flow object final FileReader fr = new FileReader("in.txt"); FileWriter fw = new FileWriter("out.txt"); // Introduce into try try (fr; fw) { // Define variables int b; // Read data while ((b = fr.read())!=-1) { // Write data fw.write(b); } } catch (IOException e) { e.printStackTrace(); } } }
Principle:
The compiler will automatically help us complete the close() and avoid exception shielding
Conclusion:
When dealing with resources that must be closed, always give priority to try with resources rather than try finally. The resulting code will be more concise and clear, and the generated exceptions will be more valuable, which try finally can't do.
Attribute set
summary
java.util.Properties inherit from Hashtable to represent a persistent property set. It uses key value structure to store data, and each key and its corresponding value are a string. This class is also used by many Java classes. For example, when obtaining system properties, system The getproperties method returns a properties object.
Properties class
Construction method
- public Properties(): create an empty property list.
Basic storage methods
- public Object setProperty(String key, String value): save a pair of properties.
- public String getProperty(String key): use the key specified in this property list to search for property values.
- Public set < string > stringpropertynames(): a collection of names of all keys.
public class ProDemo { public static void main(String[] args) throws FileNotFoundException { // Create property set object Properties properties = new Properties(); // Add key value pair element properties.setProperty("filename", "a.txt"); properties.setProperty("length", "209385038"); properties.setProperty("location", "D:\\a.txt"); // Print property set objects System.out.println(properties); // Get the attribute value through the key System.out.println(properties.getProperty("filename")); System.out.println(properties.getProperty("length")); System.out.println(properties.getProperty("location")); // Traverse the property set to get the collection of all keys Set<String> strings = properties.stringPropertyNames(); // Print key value pairs for (String key : strings ) { System.out.println(key+" -- "+properties.getProperty(key)); } } }
Output results: {filename=a.txt, length=209385038, location=D:\a.txt} a.txt 209385038 D:\a.txt filename -- a.txt length -- 209385038 location -- D:\a.txt
Flow related methods
- public void load(InputStream inStream): read key value pairs from byte input stream.
The byte input stream is used in the parameter. Through the stream object, it can be associated with a file, so that the data in the text can be loaded. Text data format:
filename=a.txt length=209385038 location=D:\a.txt
Load code demo:
public class ProDemo2 { public static void main(String[] args) throws FileNotFoundException { // Create property set object Properties pro = new Properties(); // Load information from text to property set pro.load(new FileInputStream("read.txt")); // Traversal set merge print Set<String> strings = pro.stringPropertyNames(); for (String key : strings ) { System.out.println(key+" -- "+pro.getProperty(key)); } } }
Output results: filename -- a.txt length -- 209385038 location -- D:\a.txt
tips: the data in the text must be in the form of key value pairs, which can be separated by spaces, equal signs, colons and other symbols.