Analysis of Java IO working mechanism and javaio Working Mechanism
Java IO classes are all under the java. io package. These classes can be roughly divided into the following four types:
- Byte-based I/O interfaces: InputStream and OutputStream
- Character-based I/O interfaces: Writer and Reader
- Disk-based I/O interfaces: File
- Network Operation-based I/O interface: Socket
1. Basic Structure of the IO class library 1.1 bytes-based I/O interfaces
The IO Interfaces Based on byte operations are InputStream and OutputStream respectively. The class structure of InputStream is as follows:
Similar to InputStream, The OutputStream class also has the same class structure.
For more information about how to use each subclass, see the jdk api instructions. here we need to note that the data operation methods can be combined, as shown below:
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("h:\\haha.txt"), "utf-8");
From the code above, we can see that InputStreamReader can read data from FileInputStream. From the source code, it can be seen that not only is InputStreamReader, but all IO classes can be combined in this way.
/*** Use FileReader to read the file */@ Testpublic void testFileReader () throws IOException {FileReader fileReader = new FileReader ("h: \ hahaha.txt "); char [] buff = new char [512]; StringBuffer stringBuffer = new StringBuffer (); while (fileReader. read (buff)> 0) {stringBuffer. append (buff);} fileReader. close (); System. out. print (stringBuffer. toString ();}/*** use FileReader to read the file, and then FileWriter writes it to another file */@ Testpublic void testFileReaderAndFileWriter () throws IOException {FileReader fileReader = new FileReader ("h: \ haha.txt"); char [] buff = new char [512]; StringBuffer stringBuffer = new StringBuffer (); while (fileReader. read (buff)> 0) {stringBuffer. append (buff);} System. out. println (stringBuffer. toString (); FileWriter fileWriter = new FileWriter ("h: \ haha2.txt"); fileWriter. write (stringBuffer. toString (). trim (); fileWriter. close (); System. out. println ("file written successfully");}/*** use InputStreamReader to read the file */@ Testpublic void testInputStreamReader () throws IOException {InputStreamReader inputStreamReader = new InputStreamReader (new FileInputStream ("h: \ haha.txt"), "UTF-8"); char [] buff = new char [512]; stringBuffer stringBuffer = new StringBuffer (); while (inputStreamReader. read (buff)> 0) {stringBuffer. append (buff);} System. out. println (stringBuffer. toString () ;}@ Testpublic void testIntputStream2 () throws IOException {InputStreamReader inputStreamReader = new InputStreamReader (new StringBufferInputStream ("hello world ")); char [] buff = new char [512]; int n = inputStreamReader. read (buff); System. out. println (n); System. out. println (buff);}/*** use inputStreamReader to read the file, and then OutputStreamWriter writes it to another file */@ Testpublic void testOutputStreamWriter () throws IOException {InputStreamReader inputStreamReader = new InputStreamReader (new FileInputStream ("h: \ haha.txt"), "UTF-8"); char [] buff = new char [512]; stringBuffer stringBuffer = new StringBuffer (); while (inputStreamReader. read (buff)> 0) {stringBuffer. append (buff);} System. out. println (stringBuffer. toString (); OutputStreamWriter outputStreamWriter = new OutputStreamWriter (new FileOutputStream ("h: \ haha2.txt"), "UTF-8"); outputStreamWriter. write (stringBuffer. toString (). trim (); outputStreamWriter. close ();}
Note: The FileReader class inherits InputStreamReader. FileReader reads the file stream and decodes it into char through StreamDecoder. The decoded Character Set uses the default character set. In Java, we should use a File object to determine whether a File exists. If we open it with FileOutputStream or FileWriter, it will certainly be overwritten.
2. synchronous and asynchronous, blocking, and non-blocking
Synchronous and asynchronous are for IO. Synchronization is a reliable task sequence that depends on another task only after the dependent task is completed. Either the task succeeds or fails, and the status of the two tasks can be consistent. Asynchronous mode does not need to wait for the dependent task to complete. It only notifies the dependent task to complete the task, and the dependent task is also executed immediately, as long as the entire task is completed by itself. As to whether the depended task is actually completed, the task dependent on it cannot be determined, so it is an unreliable task sequence. We can call and send text messages to compare synchronous and asynchronous operations.
Blocking and non-blocking are for the CPU. Blocking and non-blocking mainly refer to CPU consumption. Blocking means that the CPU stops and waits for a slow operation to finish the CPU before other tasks are completed. Non-blocking means that when this slow operation is executed, the CPU does other things. When this slow operation is completed, the CPU then completes subsequent operations. Although the non-blocking method can obviously improve the CPU utilization, it also has another consequence: the thread switching of the system increases. Whether the increased CPU usage time can compensate the system switching cost requires a good evaluation.
3 serialization
Java object serialization converts objects that implement the Serializable interface into a byte sequence, and can completely restore this byte sequence to the original object in the future. This process can be performed through the network, so that the serialization mechanism can automatically compensate for the differences between different operating systems. The smart aspect of corresponding serialization is that it not only saves the object's "Panorama", but also can trace the reference contained by the object and save these objects; then, you can final each such reference contained in the object, and so on.
To instantiate an object, first create some OutputStream objects and encapsulate them in an ObjectOutputStream object. In this case, you only need to call writeObject () to serialize the object, and send it to OutputStream (Object serialization is based on bytes, so InputStream and OutputStream are used to inherit the class hierarchy ). The deserialization and serialization processes are the opposite. You need to encapsulate an InputStream in ObjectInputStream, and then call readObject () to obtain a reference. It points to an Object in the upward transformation, therefore, you must perform a downward transformation to directly set them. The following is the sample code for serialization and deserialization:
@Testpublic void testWriteSerialization() { try { FileOutputStream fileOutputStream = new FileOutputStream("h:\\serialize.txt"); ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); objectOutputStream.writeObject("start"); objectOutputStream.writeObject(new Person("luoxn28", 23)); objectOutputStream.writeObject(12); objectOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } System.out.println("end...");}@Testpublic void testReadSerialization() { try { FileInputStream fileInputStream = new FileInputStream("h:\\serialize.txt"); ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); String info1 = (String) objectInputStream.readObject(); Person person = (Person) objectInputStream.readObject(); int num = (int) objectInputStream.readObject(); System.out.println(info1); System.out.println(person); System.out.println(num); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); }}
References:
1. In-depth analysis of the working mechanism of Java I/O
2. Java IO System