Common IO streams in Java and their usage

Source: Internet
Author: User

Common IO streams in Java and their usage

In Java, IO streams are divided into two categories. One is the input stream. All input streams are directly or indirectly inherited from the InputStream abstract class. The input stream is used as the data source, we can read byte data through the read method of the input stream. The other is the output stream. All output streams are directly or indirectly inherited from the OutputStream abstract class, and the output stream receives data, you can use the write method to write bytes of data. In the Java IO stream class, most input streams and output streams exist in pairs. That is, if XXXInputStream exists, XXXOutputStream exists, and vice versa. (SequenceInputStream and StringBufferInputStream are special cases. There is no corresponding SequenceOutputStream class or StringBufferOutputStream class, which will be explained later ). Many IO operations may throw an IOException, such as read, write, and close operations.
The following are common input streams in Java I/O streams. Because each input stream has its own output stream, the inheritance structure of the output stream is not listed here.

The following describes these classes in sequence and how to use them. <喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> Kernel + DQoJPHA + kernel/K/kernel + nX986qyv2 + kernel/b7do6zV/cjnxuTD + kernel/nT2tfWvdrK/kernel + kernel/kernel + vWrs/ signature + signature/K/Signature + 1xGJ5dGXK/Signature + G9q2J5dGXK/dfps/Signature + M2ouf13cml0Zc/Signature + signature/b7do6zL + signature + 1xGJ5dGXK/fingerprint + DQo8cHJlIGNsYXNzPQ = "brush: java; "> private static void testByteArrayInputOutStream(){ byte[] bytes = I am iSpring.getBytes(); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[1024]; int length = 0; try{ while((length = bais.read(buf)) > 0){ baos.write(buf, 0, length); } System.out.println(baos.toString(UTF-8)); bais.close(); baos.close(); }catch(IOException e){ e.printStackTrace(); } }

In the above example, we get byte arrays through strings as the data stream source of ByteArrayInputStream, and then write the data read to ByteArrayInputStream by reading data from ByteArrayInputStream.

FileInputStream & FileOutputStream

FileInputStream can use a File as a data source, read the stream in the File, and initialize it through a File object or File path. In its constructor, if the imported File object (or the File object indicated by the corresponding File path) does not exist or is a directory rather than a File, or cannot be opened to read data for other reasons, the FileNotFoundException exception will be thrown during the initialization phase. FileOutputStream corresponds to FileInputStream. You can use FileOutputStream to write data to the File or initialize it through the File object or File path, like FileInputStream, if the input File object (or the File object indicated by the corresponding File path) is a directory rather than a File, or the File cannot be created for other reasons to write data, will throw a FileNotFoundException exception during initialization.
The following is a sample code snippet of FileInputStream and FileOutputStream:

private static void testFileInputOutStream(){        try{            String inputFileName = D:\iWork\file1.txt;            String outputFileName = D:\iWork\file2.txt;            FileInputStream fis = new FileInputStream(inputFileName);            FileOutputStream fos = new FileOutputStream(outputFileName);            byte[] buf = new byte[1024];            int length = 0;            while ((length = fis.read(buf)) > 0){                fos.write(buf, 0, length);            }            fis.close();            fos.close();        }catch (FileNotFoundException e){            e.printStackTrace();        }catch (IOException e){            e.printStackTrace();        }    }

. If file2.txt already exists, you can input a boolean variable append to indicate whether to append data to an existing file or overwrite existing data in the initial FileOutputStream.

PipedInputStream & PipedOutputStream

PipedInputStream and PipedOutputStream are generally used in combination. These two classes are used for pipeline communication between two threads. Generally, the write operation of PipedOutputStream is executed in one thread, the PipedInputStream read operation is executed in another thread. You can bind PipedInputStream and PipedOutputStream In the constructor, or bind the two through the connect method. Once the two are bound, the read method of PipedInputStream automatically reads the data written by PipedOutputStream. The read operation of PipedInputStream is blocking. When you perform the write operation of PipedOutputStream, PipedInputStream automatically reads the content written by PipedOutputStream in another thread. If PipedOutputStream does not write data, the read method of PipedInputStream will block the thread running by the read method of PipedInputStream until data is read. It makes no sense to use PipedInputStream alone or use PipedOutputStream independently. You must bind the two to the connection through the connect method (or pass in the corresponding stream in the constructor, if one of the classes is used separately, IOException: Pipe Not Connected is triggered.
The following is a sample code snippet of PipedInputStream and PipedOutputStream:

WriterThread class

Import java. io. *; public class WriterThread extends Thread {PipedOutputStream pos = null; public WriterThread (PipedOutputStream pos) {this. pos = pos ;}@ Override public void run () {String message = this message comes from WriterThread .; try {byte [] bytes = message. getBytes (UTF-8); System. out. println (WriterThread sending information); this. pos. write (bytes); this. pos. close ();} catch (IOException e) {e. printStackTrace ();}}}

ReaderThread class

Import java. io. *; public class ReaderThread extends Thread {private PipedInputStream pis = null; public ReaderThread (PipedInputStream pis) {this. pis = pis ;}@ Override public void run () {byte [] buf = new byte [1024*8]; try {System. out. println (ReaderThread blocking waiting for receiving data ...); int length = pis. read (buf); System. out. println (ReaderThread receives the following information :); String message = new String (buf, 0, length, UTF-8); System. out. println (message); pis. close ();} catch (IOException e) {e. printStackTrace ();}}}

Test code

private  static void testPipedInputOutputStream(){        try{            PipedInputStream pis = new PipedInputStream();            PipedOutputStream pos = new PipedOutputStream();            pos.connect(pis);            WriterThread writerThread = new WriterThread(pos);            ReaderThread readerThread = new ReaderThread(pis);            readerThread.start();            writerThread.start();        }catch (IOException e){            e.printStackTrace();        }    }

In the above example, we created two thread classes WriterThread and ReaderThread. In the WriterThread constructor, we passed in a PipedOutputStream and wrote data to WriterThread when the thread executes the run method; in the ReaderThread constructor, we pass in a PipedInputStream, which is used to implement the read operation in a blocking manner when its thread executes the run method, waiting for data to be obtained. We use pos. connect (pis) to bind these two streams, and finally execute the ReaderThread and WriterThread respectively.
The output result is as follows:

We can see that even if we run the ReaderThread thread first, the PipedInputStream in ReaderThread is still waiting for the arrival of data in a blocking manner.

ObjectInputStream & ObjectOutputStream

ObjectOutputStream has a series of writeXXX methods. In its constructor, you can add an OutputStream to easily write basic data and String to the specified output stream, for example, writeBoolean, writeChar, writeInt, writeLong, writeFloat, writeDouble, writeCharts, and writeUTF. In addition, ObjectOutputStream also has the writeObject method. The Serializable interface must be implemented for the input type in the writeObject method, so that the object is serialized into a stream during the writeObject operation and written into the specified output stream. ObjectInputStream corresponds to ObjectOutputStream. ObjectInputStream has the readXXX series method that exactly corresponds to the writeXXX series methods in OutputStream. It is used to read data written by OutputStream through writeXXX.
The following is the sample code of ObjectInputStream and ObjectOutputStream:

Person class

import  java.io.Serializable;public class Person implements Serializable {    private String name = ;    private int age = 0;    public Person(String name, int age){        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public int getAge() {        return age;    }}

Test code

Private static void testObjectInputOutputStream () {try {String fileName = D: \ iWork \ file. tmp; // serialize the objects in the memory to the physical file. FileOutputStream fos = new FileOutputStream (fileName); ObjectOutputStream oos = new ObjectOutputStream (fos); String description = The following is the personnel array; person [] persons = new Person [] {new Person (iSpring, 26), new Person (Mr. sun, 27), new Person (Miss. zhou, 27)}; oos. writeObject (description); oos. writeInt (persons. length); for (Person person: persons) {oos. writeObject (person);} oos. close (); // read object information from physical file deserialization FileInputStream fiis = new FileInputStream (fileName); ObjectInputStream ois = new ObjectInputStream (fiis); String str = (String) ois. readObject (); System. out. println (str); int personCount = ois. readInt (); for (int I = 0; I <personCount; I ++) {Person person Person = (Person) ois. readObject (); StringBuilder sb = new StringBuilder (); sb. append (Name :). append (person. getName ()). append (, age :). append (person. getAge (); System. out. println (sb) ;}} catch (FileNotFoundException e) {e. printStackTrace ();} catch (IOException e) {e. printStackTrace ();} catch (ClassNotFoundException e) {e. printStackTrace ();}}

The output result is as follows:

Person implements the Serializable interface. It is worth noting that the Serializable interface is an identity interface and does not need to be implemented in any way. First, we use ObjectOutputStream to serialize array information such as Person into a stream, and then write it into FileOutputStream by calling methods such as writeObject, in this way, the basic types and objects in the memory are serialized and saved to the physical files on the hard disk. Then, read the file through FileInputStream and spread the input of the file to the constructor of ObjectInputStream. In this way, ObjectInputStream can read the basic type or object by executing the corresponding readXXX operation. When the readObject operation is performed, the returned Object type must be forcibly converted to the actual type. Note that the order of the methods in which ObjectInputStream executes the readXXX operation must be the same as that in which ObjectOutputStream executes the writeXXX operation. Otherwise, the system reads the error data or throws an exception, for example, if you start to execute writeFloat to FileOutputStream, but first execute the readInt operation in FileInputStream, no error is reported because writeFloat writes 4 bytes of data, readInt reads 4 bytes of data. Although this Float can be converted to the corresponding int, it is not the data we want, therefore, pay attention to the correspondence between readXXX operations and the execution sequence of writeXXX operations.

SequenceInputStream

SequenceInputStream combines two or more inputstreams into one InputStream logically. For example, two inputstreams are input in the constructor, in1 and in2, respectively, then, the SequenceInputStream will first read in1 during the read operation. If in1 completes reading, it will then read in2. After we understand that SequenceInputStream is used to merge two input streams into one input stream, we can understand why there is no corresponding SequenceOutputStream class, it is meaningless to split an output stream into multiple output streams.
The following is the sample code about SequenceInputStream:

private static void testSequenceInputOutputStream(){        String inputFileName1 = D:\iWork\file1.txt;        String inputFileName2 = D:\iWork\file2.txt;        String outputFileName = D:\iWork\file3.txt;        try{            FileInputStream fis1 = new FileInputStream(inputFileName1);            FileInputStream fis2 = new FileInputStream(inputFileName2);            SequenceInputStream sis = new SequenceInputStream(fis1, fis2);            FileOutputStream fos = new FileOutputStream(outputFileName);            byte[] buf = new byte[1024];            int length = 0;            while((length = sis.read(buf)) > 0){                fos.write(buf, 0, length);            }            sis.close();            fos.close();        }catch (FileNotFoundException e){            e.printStackTrace();        }catch (IOException e){            e.printStackTrace();        }    }

Then, the two input streams are used as parameters of the constructor to create the SequenceInputStream instance. Therefore, the SequenceInputStream logically merges the content of file1.txtand file2.txt into an input stream, then we read the SequenceInputStream upload file without any impact.

StringBufferInputStream

StringBufferInputStream allows you to input a String in the constructor to read bytes. During reading, it mainly calls the charAt method of String. Similar to SequenceInputStream, StringBufferInputStream does not have the corresponding OutputStream, that is, the StringBufferOutputStream class does not exist. The reason why Java does not design the StringBufferOutputStream class is also very simple. If StringBufferOutputStream exists, StringBufferOutputStream should be a String object internally updated by executing the write operation to write data, for example, it may be implemented through StringBuilder, but this is meaningless, because once our String constructor can directly input a byte array to construct a String, it is simple and clear, therefore, it is not necessary to design StringBufferOutputStream. The StringBufferInputStream class has some problems. It cannot convert character arrays to byte arrays. Therefore, this class is marked as Deprecated by Java. It is officially recommended to use StringReader as a replacement.
The following is the sample code for StringBufferInputStream:

private static void testStringBufferInputStream(){        String message = I am iSpirng.;        StringBufferInputStream sbis = new StringBufferInputStream(message);        byte[] buf = new byte[1024];        try{            int length = sbis.read(buf);            if(length > 0){                System.out.println(new String(buf, 0, length, UTF-8));            }            sbis.close();        }catch (IOException e){            e.printStackTrace();        }    }

The output result is as follows:

FilterInputStream & FilterOutputStream

FilterInputStream contains other input streams. The specific point is that an InputStream needs to be input in its constructor and saved in the field named in, filterInputStream simply overwrites all the methods. in other words, it overwrites the method simply because in each overwrite function, it only calls the method corresponding to InputStream stored in the in field, for example, when it overwrites the read method, it simply calls in. read () method. The sub-classes of FilterInputStream can further overwrite some methods to achieve a specific feature while the interface remains unchanged (for example, some sub-classes can use the cache to optimize the Read efficiency) or provide some additional practical methods. In use, FilterInputStream provides some additional features for the incoming InputStream, that is, it wraps the InputStream passed in by the constructor and uses a typical decorative mode, if you only look at the FilterInputStream class, the class itself is of little significance, because it simply overwrites some methods through the internal field in. However, if FilterInputStream is used together with its subclass, it is useful. For example, FilterInputStream has two sub-classes: BufferedInputStream and DataInputStream. These two classes are also described in detail below. BufferedInputStream optimizes read operations. Each read operation reads a large volume of data and puts it into an internally maintained byte array buffer. When the read method of BufferedInputStream is called outside, first read data from the buffer, which avoids frequent actual read operations. BufferedInputStream does not expose any other methods to the outside, however, the internal read method has been optimized, so it is more efficient when performing read operations. DataInputStream and ObjectInputStream are a bit similar. You can use some readXXX methods to read basic data types. This is a very useful method. Suppose we want to use BufferedInputStream's high reading efficiency and the readXXX method in DataInputStream. What should we do? The Code is as follows:

InputStream is = getInputStreamBySomeway();BufferedInputStream bis = new BufferedInputStream(is);DataInputStream dis = new DataInputStream(bis);

Then we can call methods such as dis. readXXX (), which is fast and convenient. This is the charm of using the FilterInputStream subclass to combine multiple features by passing through constructors. Correspondingly, BufferedOutputStream and DataOutputStream are used. BufferedOutputStream optimizes the write method and improves the write efficiency. DataOutputStream has many writeXXX methods to easily write basic data. If you want to use the writeXXX method and improve the write efficiency, you can use the following code, similar to the above Code:

OutputStream os = getOutputStreamBySomeway();BufferedOutputStream bos = new BufferedOutputStream();DataOutputStream dos = new DataOutputStream(bos);

Then, the validity rate of the dos. writeXXX method has been increased.

BufferedInputStream & BufferedOutputStream

As described above, an InputStream needs to be input in the BufferedInputStream constructor. The BufferedInputStream contains a byte array buffer, which reads data from the buf each time the read operation is executed, reading data from buf does not overhead much. If the buf has no data to be read, execute the read method of InputStream bound to it, and read a large piece of data at a time to fill the buf buffer. The default size of the buffer buf is 8192 bytes, that is, 8 K. In the constructor, we can also input a size to specify the buffer size. Because we read data from the buffer when performing the read operation of BufferedInputStream, this greatly reduces the number of read operations performed on the specified InputStream, this improves the reading efficiency. The opposite of BufferedInputStream is BufferedOutputStream. In the BufferedOutputStream constructor, We need to input an OutputStream, so that BufferedOutputStream is bound with this OutputStream. BufferedOutputStream has a byte buffer buf. During the write operation, the data to be written is first cached together and stored in the byte buffer buf. The buf size is limited, the default size is 8192 bytes, that is, 8 KB. You can also specify the buf size in the constructor. The buf will not be automatically resized as long as it is specified, so it has a limited size. Since there is a limited size, there will be a time when it has been filled, when the buf is filled, the flushBuffer method of BufferedOutputStream is called, this method will call the write method of its bound OutputStream to write the data in the buf and point the buf to zero (it can be seen as clearing the data in the buf ). If you want to make the data in the cache buf really written into OutputStream, you can call the flush method. The flushBuffer method is called internally by the flush method. Because of the existence of buf, the number of write operations performed on OutputStream is greatly reduced, and the write efficiency is optimized.
The following is a sample code snippet of BufferedInputStream and BufferedOutputStream:

private static void testBufferedInputOutputStream(){        try{            String inputFileName = D:\iWork\file1.txt;            String outputFileName = D:\iWork\file2.txt;            FileInputStream fis = new FileInputStream(inputFileName);            BufferedInputStream bis = new BufferedInputStream(fis, 1024 * 10);            FileOutputStream fos = new FileOutputStream(outputFileName);            BufferedOutputStream bos = new BufferedOutputStream(fos, 1024 * 10);            byte[] buf = new byte[1024];            int length = 0;            while ((length = bis.read(buf)) > 0){                bos.write(buf, 0, length);            }            bis.close();            bos.close();        }catch (FileNotFoundException e){            e.printStackTrace();        }catch (IOException e){            e.printStackTrace();        }    }

Running. In fact, it does not improve the efficiency by writing BufferedInputStream and Shard, thus improving the efficiency of file copy.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.