• Uncategorized
  • 0

[Java Basics-3] Understand Java IO byte stream, character stream, buffer stream

Hits: 0

foreword

Someone once asked the author of fastjson (high-speed rail, an Alibaba technical expert): “You developed fastjson, but you didn’t get much benefit. Instead, you were scolded and blamed. Why do you do this kind of thing?”

The high-speed rail replied, “Because love itself is a reward!”

This answer struck me immediately. Think about yourself, why not. Writing is a painful process, and writing with heart is even more tormenting. It requires careful consideration of every word and repeated deletions and revisions to achieve success. However, when a piece of excellent article is presented in front of you, the pain and suffering are so worth it. If these blog posts are fortunate enough to be read and recognized by everyone, it will be even more encouraging. The joy of technical people is that it can be so pure and simple.

Don’t get lost, pay attention and don’t get lost, one-click three consecutive good luck!

IO streams are an important part of Java, and we often deal with them. This blog post about Java IO is full of dry goods, and it can be called the top three in the whole network (please lightly spray!)

The following questions (the questions will continue to be added), if you can answer them correctly, then congratulations, you have a good grasp of IO knowledge, and you can close the article immediately. Instead, you can find the answer in the following article.

  1. What are the characteristics of Java IO streams?
  2. What are the types of Java IO streams?
  3. What is the relationship and difference between byte stream and character stream?
  4. Does the character stream use buffering?
  5. Are buffered streams necessarily efficient? Why?
  6. Buffered stream embodies which design pattern ideas in Java?
  7. Why implement serialization? How to implement serialization?
  8. After serializing the data, if the class file is modified again, there will be a problem in reading the data. How to solve it?

1 Introduction to Java IO

IO, that is, inand out, that is, input and output, refers to the transfer of data between applications and external devices. Common external devices include files, pipes, and network connections.

In Java, IO is processed through streams, so what is a stream ?

Stream ( Stream) is an abstract concept that refers to a series of data (characters or bytes), which is a channel for sending information in a first-in, first-out manner.

When a program needs to read data, it opens a stream to a data source, which can be a file, memory, or a network connection. Similarly, when the program needs to write data, it starts a stream to the destination. At this point you can imagine that the data “flows” through it.

Generally speaking, the characteristics of streams are as follows:

  1. First in, first out: The first data written to the output stream is read first by the input stream.
  2. Sequential access: You can write a string of bytes into the stream one by one, and read a string of bytes in the order in which they were written. You cannot access the intermediate data randomly. ( RandomAccessFileexcept)
  3. Read-only or write-only: Each stream can only be one of the input stream or the output stream, and cannot have both functions at the same time. The input stream can only be read, and the output stream can only be written. In a data transmission channel, if you want to write data and read data, you need to provide two streams respectively.

1.1 IO flow classification

There are three main classification methods of IO streams:

  1. According to the direction of data flow: input stream, output stream
  2. By processing data unit: byte stream, character stream
  3. By function: node flow, process flow

1. Input stream and output stream

Input and output are relative to the application, such as file reading and writing, reading a file is an input stream, and writing a file is an output stream, which is easy to confuse.

2. Byte stream and character stream

[The usage of byte stream] and character stream is almost the same. The difference is that byte stream and character stream operate on different data units. The unit of byte stream operation is the byte whose data unit is 8 bits, and the character stream operates on data. The unit is a 16-bit character.

Why have a character stream?

Characters in Java use the Unicode standard. In Unicode encoding, an English letter or a Chinese character is two bytes.
In UTF-8 encoding, a Chinese character is 3 bytes. For example, in the figure below, the 5 Chinese characters of “Yunshen do not know where” correspond to 15 bytes: -28-70-111-26-73-79-28-72-115-25-97-91-27-92 -124

Then the problem comes. If you use byte stream to process Chinese, if you read and write the number of bytes corresponding to one character at a time, there will be no problem. Once the bytes corresponding to one character are split, there will be garbled characters. In order to deal with these Chinese characters more conveniently, Java has introduced the [character stream] .

Other differences between byte stream and character stream:

  1. Byte streams are generally used to process files of image, video, audio, PPT, Word and other types. Character streams are generally used to process plain text files, such as TXT files, but cannot process non-text files such as images and videos. In one sentence: byte streams can handle all files, while character streams can only handle plain text files.
  2. The byte stream itself has no buffer. Compared with the byte stream, the buffered byte stream has a very high efficiency improvement. The character stream itself has a buffer, and the efficiency improvement of the buffered character stream relative to the character stream is not so great. See the efficiency comparison at the end of the article for details.

Taking writing a file as an example, we look at the source code of the character stream and find that the buffer is indeed used:

3. Node flow and processing flow

Node stream : a stream class that directly manipulates data read and write, such asFileInputStream

Processing stream : linking and encapsulating an existing stream, providing powerful and flexible read and write functions for the program by processing data, such as BufferedInputStream(buffered byte stream)

Processing streams and node streams apply Java’s decorator design pattern.

The following figure vividly depicts the node flow and the processing flow. The processing flow is the encapsulation of the node flow, and the final data processing is completed by the node flow.
Among the many processing streams, a very important one is the buffer stream .

We know that the interaction between the program and the disk is very slow compared to the memory operation, and it is easy to become the performance bottleneck of the program. Reducing the interaction between the program and the disk is an effective means to improve the efficiency of the program. Buffered streams apply this idea: ordinary streams read and write one byte at a time, while buffered streams set up a buffer in memory. The buffer stores enough data to be operated before interacting with memory or disk. In this way, under the condition that the total amount of data remains unchanged, the number of interactions is reduced by increasing the amount of data for each interaction.

Think of an example in life. When we move bricks, it is definitely inefficient to load the car piece by piece. We can use a trolley, first load the bricks onto the trolley, and then push the trolley to the front of the cart to load the bricks onto the cart. In this example, the trolley can be regarded as a buffer zone. The existence of the trolley reduces the number of loading times and improves the efficiency.
It should be noted that the buffer stream efficiency must be high? Not necessarily. In some cases, the buffer stream efficiency is lower. For details, see IO Stream Efficiency Comparison.

The complete IO classification diagram is as follows:

1.2 Case practice

Next, let’s see how to use Java IO.

An example of text reading and writing , which is what the article said at the beginning, would be “Panasonic asks the boy, the teacher goes to collect medicine. Only in this mountain, Yunshen does not know where to go.” Write the local text, then read the content from the file and output to the console.

1. FileInputStream, FileOutputStream (byte stream)

The byte stream method is less efficient and is not recommended to use

public class IOTest {
    public static void main(String[] args) throws IOException {
        File file = new File("D:/test.txt");

        write(file);
        System.out.println(read(file));
    }

    public static void write(File file) throws IOException {
        OutputStream os = new FileOutputStream(file, true);

        // The string to be written 
        String string = "Panasonic asked the boy, the teacher went to collect medicine. Only in this mountain, Yunshen does not know where to go." ;
         // Write to the file 
        os.write( string .getBytes ());
         // close the stream
        os.close();
    }

    public static String read(File file) throws IOException {
        InputStream in = new FileInputStream(file);

        // How many bytes to take at one time 
        byte [] bytes = new  byte [ 1024 ];
         // used to receive the read byte array 
        StringBuilder sb = new StringBuilder();
         // the length of the read byte array, -1 means no data 
        int length = 0 ;
         // loop to get data 
        while ((length = in .read(bytes)) != -1 ) {
             // convert the read content into a string 
            sb.append( new String(bytes, 0 , length));
        }
        // close the stream 
        in .close();

        return sb.toString();
    }
}

2. BufferedInputStream, BufferedOutputStream (buffered byte stream)

The buffered byte stream is designed for high efficiency, and the real read and write operations are still based on FileOutputStreamsum FileInputStream, so it is not surprising that the parameters of its constructor are objects of these two classes.

public class IOTest {

    public  static  void  write ( File file ) throws IOException {
         // Buffer byte stream to improve efficiency 
        BufferedOutputStream bis = new BufferedOutputStream( new FileOutputStream(file, true ));

        // The string to be written 
        String string = "Panasonic asked the boy, the teacher went to collect medicine. Only in this mountain, Yunshen does not know where to go." ;
         // Write to the file 
        bis.write( string .getBytes ());
         // close the stream
        bis.close();
    }

    public static String read(File file) throws IOException {
        BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file));

        // How many bytes to take at one time 
        byte [] bytes = new  byte [ 1024 ];
         // used to receive the read byte array 
        StringBuilder sb = new StringBuilder();
         // the length of the read byte array, When it is -1, it means there is no data 
        int length = 0 ;
         // loop to get data 
        while ((length = fis.read(bytes)) != -1 ) {
             // Convert the read content to a string 
            sb.append( new String(bytes, 0 , length));
        }
        // close the stream
        fis.close();

        return sb.toString();
    }
}

3. InputStreamReader, OutputStreamWriter (character stream)

The character stream is suitable for reading and writing text files , and the OutputStreamWriterclass is actually FileOutputStreamimplemented with the help of the class, so its construction method is FileOutputStreamthe object

public class IOTest {

    public  static  void  write (File file) throws IOException {
         // OutputStreamWriter can display the specified character set, otherwise use the default character set 
        OutputStreamWriter osw = new OutputStreamWriter( new FileOutputStream(file, true ), "UTF-8" );

        // The string to be written 
        String string = "Panasonic asked the boy, and the teacher went to collect medicine. Only in this mountain, Yunshen does not know where to go." ;
        osw.write(string);
        osw.close();
    }

    public static String read(File file) throws IOException {
        InputStreamReader isr = new InputStreamReader( new FileInputStream(file), "UTF-8" );
         // character array: how many characters to read at a time 
        char [] chars = new  char [ 1024 ];
         // character array for each read First append to StringBuilder 
        StringBuilder sb = new StringBuilder();
         // The length of the read character array, when it is -1, means there is no data 
        int length;
         // Loop to get the data 
        while ((length = isr.read(chars)) != -1 ) {
             // Convert the read content to a string 
            sb.append(chars, 0 , length);
        }
        // close the stream
        isr.close();

        return sb.toString()
    }
}

4. Character stream convenience class

Java provides FileWriterand FileReadersimplifies reading and writing of character streams, new FileWriterequivalent tonew OutputStreamWriter(new FileOutputStream(file, true))

public class IOTest {

    public static void write(File file) throws IOException {
        FileWriter fw = new FileWriter(file, true);

        // The string to be written 
        String string = "Panasonic asked the boy, and the teacher went to collect medicine. Only in this mountain, Yunshen does not know where to go." ;
        fw.write(string);
        fw.close();
    }

    public static String read(File file) throws IOException {
        FileReader fr = new FileReader(file);
         // How many bytes to take at a time 
        char [] chars = new  char [ 1024 ];
         // used to receive the read byte array 
        StringBuilder sb = new StringBuilder();
         // The length of the read byte array, -1 means no data 
        int length;
         // loop to get data 
        while ((length = fr.read(chars)) != -1 ) {
             // Convert the read content into a string 
            sb.append(chars, 0 , length);
        }
        // close the stream
        fr.close();

        return sb.toString();
    }
}

5. BufferedReader, BufferedWriter (character buffer stream)

public class IOTest {

    public  static  void  write ( File file ) throws IOException {
         // BufferedWriter fw = new BufferedWriter(new OutputStreamWriter(new 
        // FileOutputStream(file, true), "UTF-8")); 
        // FileWriter can greatly simplify the code 
        BufferedWriter bw = new BufferedWriter( new FileWriter(file, true ));

        // The string to be written 
        String string = "Panasonic asked the boy, and the teacher went to collect medicine. Only in this mountain, Yunshen does not know where to go." ;
        bw.write(string);
        bw.close();
    }

    public static String read(File file) throws IOException {
        BufferedReader br = new BufferedReader( new FileReader(file));
         // used to receive the read byte array 
        StringBuilder sb = new StringBuilder();

        // read data row by row
        String line;
        // Loop to get data 
        while ((line = br.readLine()) != null ) {
             // Convert the read content to a string
            sb.append(line);
        }
        // close the stream
        br.close();

        return sb.toString();
    }
}

2 IO stream objects

In the first section, we have a general understanding of IO and completed several cases, but we still lack a more detailed understanding of IO, then we will break down Java IO in detail and sort out a complete knowledge system.

Java provides more than 40 classes, we only need to understand the more important ones in detail to meet the daily application.

2.1 File class

FileA class is a class used to manipulate files, but it cannot manipulate the data in the file.

public class File extends Object implements Serializable, Comparable<File>

FileThe class implements Serializable, Comparable<File>, indicating that it supports serialization and sorting.

Constructor of the File class

method name illustrate
File(File parent, String child) Creates a new File instance from the parent abstract pathname and child pathname strings.
File(String pathname) Creates a new File instance by converting the given pathname string to an abstract pathname.
File(String parent, String child) Creates a new File instance from the parent pathname string and the child pathname string.
File(URI uri) Creates a new File instance by converting the given file: URI to an abstract pathname.

Common methods of the File class

method illustrate
createNewFile() Inseparably creates a new empty file if and only if no file with the name specified by this abstract pathname exists.
delete() Deletes the file or directory represented by this abstract pathname.
exists() Tests whether the file or directory represented by this abstract pathname exists.
getAbsoluteFile() Returns the absolute pathname form of this abstract pathname.
getAbsolutePath() Returns the absolute pathname string for this abstract pathname.
length() Returns the length of the file represented by this abstract pathname.
mkdir() Creates the directory specified by this abstract pathname.

File class usage example

public class FileTest {
    public static void main(String[] args) throws IOException {
        File file = new File("C:/Mu/fileTest.txt");

        // Determine if the file exists 
        if (!file.exists()) {
             // Create if it does not exist
            file.createNewFile();
        }
        System.out .println ( "Absolute path of file: " + file.getAbsolutePath()) ;System.out.println ( "Size of file: " + file.length()) 
        ;

        // Delete Files
        file.delete();
    }
}

2.2 Byte Stream

InputStreamAnd OutputStreamare two abstract classes, which are the base classes of byte streams. All concrete byte stream implementation classes inherit these two classes respectively.

For InputStreamexample, it inherits Object, implementsCloseable

public abstract class InputStream
extends Object
implements Closeable

InputStreamThere are many implementation subclasses of the class, some of the more commonly used are listed below:
Let’s elaborate on the classes in the above image:

  1. InputStream: InputStreamis the abstract base class of all byte input streams. As mentioned earlier, abstract classes cannot be instantiated, but actually exist as templates, and define methods for processing input streams for all implementation classes.
  2. FileInputSream: The file input stream, a very important byte input stream, is used to read from the file.
  3. PipedInputStream: Pipeline byte input stream, which can realize pipe communication between multiple threads.
  4. ByteArrayInputStream: Byte array input stream, read from the byte array (byte[]) in units of bytes, that is, store the resource files in the form of bytes into the byte array in this class .
  5. FilterInputStream: Decorator class, the specific decorator inherits this class, these classes are processing classes, the role is to encapsulate the node class and implement some special functions.
  6. DataInputStream: Data input stream, which is used to decorate other input streams to “allow an application to read basic Java data types from the underlying input stream in a machine-independent manner”.
  7. BufferedInputStream: Buffer stream, decorate the node stream, there will be a buffer area inside to store bytes, every time the buffer area is filled and then sent, instead of sending one byte or two bytes, it is more efficient high.
  8. ObjectInputStream: Object input stream, used to provide persistent storage of basic data or objects . In layman’s terms, it means that objects can be transferred directly, which is usually used in deserialization. It is also a processing stream, and the input parameter of the constructor is an InputStreaminstance object.

OutputStreamClass inheritance diagram:

OutputStreamThe class inheritance relationship is InputStreamsimilar, it should be noted that PrintStream.

2.3 Character stream

Similar to byte streams, character streams also have two abstract base classes, Readerand Writer. Other character stream implementation classes inherit these two classes.

For Readerexample, its main implementation subclass is as follows:
Detailed description of each class:

  1. InputStreamReader: A bridge from a byte stream to a character stream (the InputStreamReaderconstructor parameter is FileInputStreaman instance object), which reads bytes and decodes them into characters using the specified character set. The character set it uses can be specified by name, given explicitly, or the platform’s default character set can be accepted.
  2. BufferedReader: Read text from a character input stream, setting up a buffer for efficiency. BufferedReaderIt is the right InputStreamReaderencapsulation. The input parameter of the former constructor is an instance object of the latter.
  3. FileReader: Convenience class for reading character files, new FileReader(File file)equivalent to new InputStreamReader(new FileInputStream(file, true),"UTF-8"), but FileReadercannot specify character encoding and default byte buffer size.
  4. PipedReader: Pipe character input stream. Implement pipeline communication between multiple threads.
  5. CharArrayReader: CharMedia stream to read data from the array.
  6. StringReader: The media stream Stringto read data from.

WriterSimilar to the Readerstructure, the direction is opposite, and will not be repeated. The only difference is Writerthe subclass of PrintWriter.

2.4 Serialization

to be continued…

3 IO stream method

3.1 Byte Stream Method

InputStreamThe main method of byte input stream :

  • read(): Read a byte of data from this input stream.
  • read(byte[] b): Reads up to b.length bytes of data from this input stream into a byte array.
  • read(byte[] b, int off, int len): Reads up to len bytes of data from this input stream into a byte array.
  • close(): Closes this input stream and releases all system resources associated with this stream.

OutputStreamThe main method of byte output stream :

  • write(byte[] b): Writes b.length bytes from the specified byte array to this file output stream.
  • write(byte[] b, int off, int len): Writes len bytes starting at offset off in the specified byte array to this file output stream.
  • write(int b): Write the specified bytes to this file output stream.
  • close(): Closes this input stream and releases all system resources associated with this stream.

3.2 Character stream method

ReaderThe main methods of character input stream :

  • read(): Read a single character.
  • read(char[] cbuf): Read characters into an array.
  • read(char[] cbuf, int off, int len): Read characters into a part of an array.
  • read(CharBuffer target): Attempt to read characters into the specified character buffer.
  • flush(): Flush the stream’s buffer.
  • close(): Close this stream, but flush it first.

WriterThe main methods of character output stream :

  • write(char[] cbuf): Write a character array.
  • write(char[] cbuf, int off, int len): Writes a part of a character array.
  • write(int c): Write a single character.
  • write(String str): Write a string.
  • write(String str, int off, int len): Write a part of the string.
  • flush(): Flush the stream’s buffer.
  • close(): Close this stream, but flush it first.

In addition, the character buffer stream has two unique methods:

  • BufferedWriterclass newLine(): Writes a line separator. This method will automatically adapt to the line separator of the system on which it is running.
  • BufferedReaderClass readLine(): Reads a line of text.

4 Additional content

4.1 Bits, Bytes, Characters

Byte is a unit of measurement, indicating the amount of data. It is a unit of measurement used by computer information technology to measure storage capacity. Usually, a byte is equal to eight bits.

Characters Letters, numbers, words and symbols used in computers, such as ‘A’, ‘B’, ‘$’, ‘&’, etc.

Generally, one letter or character occupies one byte in English, and one Chinese character is represented by two bytes.

Bytes and characters:

  • In ASCII code, one English letter (case-insensitive) is one byte, and one Chinese character is two bytes.
  • In UTF-8 encoding, one English word is one byte, and one Chinese word is three bytes.
  • In Unicode encoding, one English is one byte, and one Chinese is two bytes.
  • Symbol: English punctuation is one byte, Chinese punctuation is two bytes. For example: English period. The size of 1 byte, Chinese period. 2 bytes in size.
  • In UTF-16 encoding, one English alphabet character or one Chinese character needs 2 bytes to store (some Chinese characters in the Unicode extension area need 4 bytes to store).
  • In UTF-32 encoding, storage of any character in the world requires 4 bytes.

4.2 IO Stream Efficiency Comparison

First, compare the efficiency of ordinary byte streams and buffered byte streams:

public class MyTest {
    public static void main(String[] args) throws IOException {
        File file = new File("C:/Mu/test.txt");
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < 3000000; i++) {
            sb.append("abcdefghigklmnopqrstuvwsyz");
        }
        byte[] bytes = sb.toString().getBytes();

        long start = System.currentTimeMillis();
        write(file, bytes);
        long end = System.currentTimeMillis();

        long start2 = System.currentTimeMillis();
        bufferedWrite(file, bytes);
        long end2 = System.currentTimeMillis();

        System.out.println( "Common byte stream time: " + (end - start) + " ms" );
        System.out.println( "Time to buffer byte stream: " + (end2 - start2) + " ms" );

    }

    // Normal character style 
    public  static  void  write (File file, byte [] bytes)  throws IOException {
        OutputStream os = new FileOutputStream(file);
        os.write(bytes);
        os.close();
    }

    // buffered byte stream 
    public  static  void  bufferedWrite (File file, byte [] bytes)  throws IOException {
        BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(file));
        bo.write(bytes);
        bo.close();
    }
}

operation result:

Normal byte stream time: 250 ms
Time to buffer byte stream: 268 ms

This result surprised me, doesn’t it mean that the buffer flow is very efficient? To know why, you can only go to the source code to find the answer. The way to look at the byte buffer stream write:

public synchronized void write(byte b[], int off, int len) throws IOException {
    if (len >= buf.length) {
        /* If the request length exceeds the size of the output buffer,
           flush the output buffer and then write the data directly.
           In this way buffered streams will cascade harmlessly. */
        flushBuffer();
        out.write(b, off, len);
        return;
    }
    if (len > buf.length - count) {
        flushBuffer();
    }
    System.arraycopy(b, off, buf, count, len);
    count += len;
}

The comments are very clear: if the request length exceeds the size of the output buffer, the output buffer is flushed, and then the data is written directly. This way, the buffered streams will cascade harmlessly.

However, as for why it is designed like this, I don’t want to understand. Anyone who understands can leave a message and give pointers.

Based on the above situation, in order to compare the efficiency gap between ordinary byte streams and buffered byte streams, it is necessary to avoid reading and writing long strings directly. Therefore, the following comparison case is designed: using byte streams and buffered bytes Streams copy files individually.

public class MyTest {
    public static void main(String[] args) throws IOException {
        File data = new File("C:/Mu/data.zip");
        File a = new File("C:/Mu/a.zip");
        File b = new File("C:/Mu/b.zip");

        StringBuilder sb = new StringBuilder();

        long start = System.currentTimeMillis();
        copy(data, a);
        long end = System.currentTimeMillis();

        long start2 = System.currentTimeMillis();
        bufferedCopy(data, b);
        long end2 = System.currentTimeMillis();
System.out 
        .println ( "Common byte stream time: " + (end - start) + " ms" );
        System.out .println ( "Time to buffer byte stream: " + ( end2 - start2) + " ms" );
    }

    // Ordinary byte stream 
    public  static  void  copy ( File in , File out ) throws IOException {
         // Encapsulating data source 
        InputStream is = new FileInputStream( in );
         // Encapsulating destination 
        OutputStream os = new FileOutputStream( out );

        int by = 0;
        while ((by = is.read()) != -1) {
            os.write(by);
        }
        is.close();
        os.close();
    }

    // Buffered byte stream 
    public  static  void  bufferedCopy ( File in , File out ) throws IOException {
         // Encapsulate data source 
        BufferedInputStream bi = new BufferedInputStream( new FileInputStream( in ));
         // Encapsulate destination 
        BufferedOutputStream bo = new BufferedOutputStream( new FileOutputStream( out ));

        int by = 0;
        while ((by = bi.read()) != -1) {
            bo.write(by);
        }
        bo.close();
        bi.close();
    }
}

operation result:

Normal byte stream time: 184867 ms
Time to buffer byte stream: 752 ms

This time, the efficiency difference between the normal byte stream and the buffered byte stream is obvious, reaching 245 times.

Let’s take a look at the efficiency comparison between character stream and buffered character stream:

public  class  IOTest {
     public  static  void  main ( String[] args ) throws IOException {
         // data preparation
        dataReady();

        File data = new File("C:/Mu/data.txt");
        File a = new File("C:/Mu/a.txt");
        File b = new File("C:/Mu/b.txt");
        File c = new File("C:/Mu/c.txt");

        long start = System.currentTimeMillis();
        copy(data, a);
        long end = System.currentTimeMillis();

        long start2 = System.currentTimeMillis();
        copyChars(data, b);
        long end2 = System.currentTimeMillis();

        long start3 = System.currentTimeMillis();
        bufferedCopy(data, c);
        long end3 = System.currentTimeMillis();

        System.out.println ( "Common byte stream 1 time-consuming: " + (end - start) + " ms, file size: " + a.length () / 1024 + " kb" );
        System.out .println ( "Ordinary byte stream 2 time: " + ( end2 - start2) + " ms, file size: " + b.length() / 1024 + "kb" );
        System.out .println ( "Time to buffer byte stream: " + (end3 - start3) + " ms, file size: " + c.length() / 1024 + "kb" );
    }

    // Ordinary character streams do not use arrays 
    public  static  void  copy ( File in , File out ) throws IOException {
        Reader reader = new FileReader(in);
        Writer writer = new FileWriter(out);

        int ch = 0;
        while ((ch = reader.read()) != -1) {
            writer.write((char) ch);
        }
        reader.close();
        writer.close();
    }

    // Ordinary character stream uses character stream 
    public  static  void  copyChars ( File in , File out ) throws IOException {
        Reader reader = new FileReader(in);
        Writer writer = new FileWriter(out);

        char[] chs = new char[1024];
        while ((reader.read(chs)) != -1) {
            writer.write(chs);
        }
        reader.close();
        writer.close();
    }

    // buffered character stream 
    public  static  void  bufferedCopy ( File in , File out ) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader(in));
        BufferedWriter bw = new BufferedWriter(new FileWriter(out));

        String line = null;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        // release resources
        bw.close();
        br.close();
    }

    // data preparation 
    public  static  void  dataReady () throws IOException {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 600000; i++) {
            sb.append("abcdefghijklmnopqrstuvwxyz");
        }
        OutputStream os = new FileOutputStream(new File("C:/Mu/data.txt"));
        os.write(sb.toString().getBytes());

        os.close();
        System.out.println ( "Finished" ) ;
    }
}

operation result:

Normal character stream 1 time: 1337 ms, file size: 15234 kb
Normal character stream 2 time: 82 ms, file size: 15235 kb
Buffering character stream time: 205 ms, file size: 15234 kb

Tested many times, the results are similar, it can be seen that the efficiency of the character buffer stream has not been significantly improved, and we should use its readLine()sum newLine()method more.

4.3 NIO

to be continued…

You may also like...

Leave a Reply

Your email address will not be published.