Six methods of file writing, this method has the best performance

There are only two ways to operate files in Java: character stream and byte stream, and there are many implementation classes of byte stream and character stream. Therefore, we can choose a variety of classes to implement when writing files. In this article, we will review these methods and test their performance in order to select the best write method for us.

Before we begin, let's understand the definitions and differences of several basic concepts: stream, byte stream and character stream.

0. What is flow?

"Flow" in Java is an abstract concept and a metaphor. Just like water flow, water flow flows from one end to the other, while "water flow" in Java is data, and data will "flow" from one end to the other.

According to the direction of the stream, we can divide the stream into input stream and output stream. When the program needs to read data from the data source, an input stream will be opened. On the contrary, when writing data to a data source destination, an output stream will also be opened. The data source can be file, memory or network.

1. What is a byte stream?

The basic unit of byte stream is byte. A byte is usually 8 bits. It is used to process binary (data). Byte stream has two base classes: InputStream and OutputStream.

The inheritance diagram of common byte stream is shown in the following figure:

2. What is character stream?

The basic unit of character stream is Unicode and its size is two bytes. It is usually used to process text data. The two base classes of character stream are reader (input character stream) and writer (output character stream).

The inheritance diagram of common character stream is shown in the following figure:

3. Classification of flow

Streams can be classified according to different dimensions. For example, they can be classified according to the direction of the stream, the transmission unit, and the function of the stream, such as the following.

① Classification by flow direction

② Classification according to transmission data units

③ Classification according to function

4. Six methods of writing files

The method of writing files mainly comes from the subclasses of character stream writer and output byte stream OutputStream, as shown in the following figure:

Method 1: filewriter

Filewriter is a member of the "character stream" system and the basic class for file writing. It contains five constructors, which can pass a specific file location or file object. The second parameter indicates whether to append the file. The default value is false, which means to rewrite the file content rather than append the file content (we will talk about how to append the file later).

/**
  * 方法 1:使用 FileWriter 写文件
  * @param filepath 文件目录
  * @param content  待写入内容
  * @throws IOException
  */
public static void fileWriterMethod(String filepath,String content) throws IOException {
    try (FileWriter fileWriter = new FileWriter(filepath)) {
        fileWriter.append(content);
    }
}

Just pass in the specific file path and the content to be written. The calling code is as follows:

public static void main(String[] args) {
    fileWriterMethod("/Users/mac/Downloads/io_test/write1.txt","哈喽,Java中文社群.");
}

Then we open the written file and the results are as follows:

Method 2: bufferedwriter

Bufferedwriter is also a member of the character stream system. Different from filewriter, bufferedwriter has its own buffer, so it has higher performance in writing files (the two will be tested below).

Tips: buffer

Buffer, also known as cache, is a part of memory space. In other words, a certain storage space is reserved in the memory space, which is used to buffer the input or output data. This part of the reserved space is called buffer.

Advantages of buffer take the writing of file stream as an example. If we do not use buffer, the CPU will interact with low-speed storage device, that is, disk, every time we write, Then the speed of the whole file will be limited by the low-speed storage device (disk). However, if a buffer is used, each write operation will first save the data in the cache memory. When the data in the buffer reaches a certain threshold, the file will be written to the disk at one time. Because the write speed of the memory is much faster than that of the disk, the write speed of the file will be greatly improved when there is a buffer.

After understanding the advantages of cache, let's return to the topic of this article. Next, we use bufferedwriter to write files. The implementation code is as follows:

/**
 * 方法 2:使用 BufferedWriter 写文件
 * @param filepath 文件目录
 * @param content  待写入内容
 * @throws IOException
 */
public static void bufferedWriterMethod(String filepath,String content) throws IOException {
    try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filepath))) {
        bufferedWriter.write(content);
    }
}

The calling code is similar to method 1 and will not be repeated here.

Method 3: printwriter

Printwriter is also a member of the character stream system. Although it is called "character print stream", it can also be used to write files. The implementation code is as follows:

/**
 * 方法 3:使用 PrintWriter 写文件
 * @param filepath 文件目录
 * @param content  待写入内容
 * @throws IOException
 */
public static void printWriterMethod(String filepath,String content) throws IOException {
    try (PrintWriter printWriter = new PrintWriter(new FileWriter(filepath))) {
        printWriter.print(content);
    }
}

As can be seen from the above code, both printwriter and bufferedwriter must complete the call based on the filewriter class.

Method 4: fileoutputstream

The above three examples are about the operation of writing a file with a character stream, and next we will use a byte stream to write the file. We will use the GetBytes () method of string to convert the string into a binary file first, and then write the file. Its implementation code is as follows:

/**
 * 方法 4:使用 FileOutputStream 写文件
 * @param filepath 文件目录
 * @param content  待写入内容
 * @throws IOException
 */
public static void fileOutputStreamMethod(String filepath,String content) throws IOException {
    try (FileOutputStream fileOutputStream = new FileOutputStream(filepath)) {
        byte[] bytes = content.getBytes();
        fileOutputStream.write(bytes);
    }
}

Method 5: bufferedoutputstream

Bufferedoutputstream is a member of the byte stream system. Different from fileoutputstream, it has its own buffer function, so its performance is better. Its implementation code is as follows:

/**
 * 方法 5:使用 bufferedoutputstream 写文件
 * @param filepath 文件目录
 * @param content  待写入内容
 * @throws IOException
 */
public static void bufferedoutputstreamMethod(String filepath,String content) throws IOException {
    try (bufferedoutputstream bufferedoutputstream = new bufferedoutputstream(
            new FileOutputStream(filepath))) {
        bufferedoutputstream.write(content.getBytes());
    }
}

Method 6: files

The next operation method is different from the previous code. Next, we use a new file operation class files provided in JDK 7 to write files.

Files class is a new class for operating files added by JDK 7. It provides a large number of methods for processing files, such as file copying, reading, writing, obtaining file attributes, quickly traversing file directories, etc. these methods greatly facilitate file operation. Its implementation code is as follows:

/**
 * 方法 6:使用 Files 写文件
 * @param filepath 文件目录
 * @param content  待写入内容
 * @throws IOException
 */
public static void filesTest(String filepath,String content) throws IOException {
    Files.write(Paths.get(filepath),content.getBytes());
}

All of the above methods can write files. Which method has higher performance? Next, let's test it.

5. Performance test

Let's first build a relatively large string, then use the above six methods to test the file writing speed, and finally print the results. The test code is as follows:

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;

public class WriteExample {
    public static void main(String[] args) throws IOException {
        // 构建写入内容
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < 1000000; i++) {
            stringBuilder.append("ABCDEFGHIGKLMNOPQRSEUVWXYZ");
        }
        // 写入内容
        final String content = stringBuilder.toString();
        // 存放文件的目录
        final String filepath1 = "/Users/mac/Downloads/io_test/write1.txt";
        final String filepath2 = "/Users/mac/Downloads/io_test/write2.txt";
        final String filepath3 = "/Users/mac/Downloads/io_test/write3.txt";
        final String filepath4 = "/Users/mac/Downloads/io_test/write4.txt";
        final String filepath5 = "/Users/mac/Downloads/io_test/write5.txt";
        final String filepath6 = "/Users/mac/Downloads/io_test/write6.txt";

        // 方法一:使用 FileWriter 写文件
        long stime1 = System.currentTimeMillis();
        fileWriterTest(filepath1,content);
        long etime1 = System.currentTimeMillis();
        System.out.println("FileWriter 写入用时:" + (etime1 - stime1));

        // 方法二:使用 BufferedWriter 写文件
        long stime2 = System.currentTimeMillis();
        bufferedWriterTest(filepath2,content);
        long etime2 = System.currentTimeMillis();
        System.out.println("BufferedWriter 写入用时:" + (etime2 - stime2));

        // 方法三:使用 PrintWriter 写文件
        long stime3 = System.currentTimeMillis();
        printWriterTest(filepath3,content);
        long etime3 = System.currentTimeMillis();
        System.out.println("PrintWriterTest 写入用时:" + (etime3 - stime3));

        // 方法四:使用 FileOutputStream  写文件
        long stime4 = System.currentTimeMillis();
        fileOutputStreamTest(filepath4,content);
        long etime4 = System.currentTimeMillis();
        System.out.println("FileOutputStream 写入用时:" + (etime4 - stime4));

        // 方法五:使用 bufferedoutputstream 写文件
        long stime5 = System.currentTimeMillis();
        bufferedoutputstreamTest(filepath5,content);
        long etime5 = System.currentTimeMillis();
        System.out.println("bufferedoutputstream 写入用时:" + (etime5 - stime5));

        // 方法六:使用 Files 写文件
        long stime6 = System.currentTimeMillis();
        filesTest(filepath6,content);
        long etime6 = System.currentTimeMillis();
        System.out.println("Files 写入用时:" + (etime6 - stime6));

    }

    /**
     * 方法六:使用 Files 写文件
     * @param filepath 文件目录
     * @param content  待写入内容
     * @throws IOException
     */
    private static void filesTest(String filepath,String content) throws IOException {
        Files.write(Paths.get(filepath),content.getBytes());
    }

    /**
     * 方法五:使用 bufferedoutputstream 写文件
     * @param filepath 文件目录
     * @param content  待写入内容
     * @throws IOException
     */
    private static void bufferedoutputstreamTest(String filepath,String content) throws IOException {
        try (bufferedoutputstream bufferedoutputstream = new bufferedoutputstream(
                new FileOutputStream(filepath))) {
            bufferedoutputstream.write(content.getBytes());
        }
    }

    /**
     * 方法四:使用 FileOutputStream  写文件
     * @param filepath 文件目录
     * @param content  待写入内容
     * @throws IOException
     */
    private static void fileOutputStreamTest(String filepath,String content) throws IOException {
        try (FileOutputStream fileOutputStream = new FileOutputStream(filepath)) {
            byte[] bytes = content.getBytes();
            fileOutputStream.write(bytes);
        }
    }

    /**
     * 方法三:使用 PrintWriter 写文件
     * @param filepath 文件目录
     * @param content  待写入内容
     * @throws IOException
     */
    private static void printWriterTest(String filepath,String content) throws IOException {
        try (PrintWriter printWriter = new PrintWriter(new FileWriter(filepath))) {
            printWriter.print(content);
        }
    }

    /**
     * 方法二:使用 BufferedWriter 写文件
     * @param filepath 文件目录
     * @param content  待写入内容
     * @throws IOException
     */
    private static void bufferedWriterTest(String filepath,String content) throws IOException {
        try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filepath))) {
            bufferedWriter.write(content);
        }
    }

    /**
     * 方法一:使用 FileWriter 写文件
     * @param filepath 文件目录
     * @param content  待写入内容
     * @throws IOException
     */
    private static void fileWriterTest(String filepath,String content) throws IOException {
        try (FileWriter fileWriter = new FileWriter(filepath)) {
            fileWriter.append(content);
        }
    }
}

Before viewing the results, we first go to the corresponding folder to see if the written file is normal, as shown in the following figure:

From the above results, we can see that the string write stream bufferedwriter with buffer has the best performance, and the files has the slowest performance.

6. Expand knowledge: add content

The above code will rewrite the file. If you only want to add content on the original basis, you need to set an append parameter to true when creating the write stream. For example, if we use filewriter to append the file, the implementation code is as follows:

public static void fileWriterMethod(String filepath,String content) throws IOException {
    // 第二个 append 的参数传递一个 true = 追加文件的意思
    try (FileWriter fileWriter = new FileWriter(filepath,true)) {
        fileWriter.append(content);
    }
}

If bufferedwriter or printwriter is used, it is also necessary to set the parameter of append to true when building the new filewriter class. The implementation code is as follows:

try (BufferedWriter bufferedWriter = new BufferedWriter(
    new FileWriter(filepath,true))) {
    bufferedWriter.write(content);
}

In contrast, if the files class wants to implement the additional writing method of the file, it needs to pass an additional standardopenoption when calling the write method The parameter of append, and its implementation code is as follows:

Files.write(Paths.get(filepath),content.getBytes(),StandardOpenOption.APPEND);

7. Summary

In this article, we show six methods of writing files, which are divided into three categories: character stream writing, byte stream writing and files class writing. The most convenient operation is the files class, but its performance is not very good. If performance is required, it is recommended to use a stream with a cache to complete the operation, such as bufferedwriter or bufferedoutputstream. If the content to be written is a string, bufferedwriter is recommended. If the content to be written is a binary file, bufferedoutputstream is recommended.

Reference & acknowledgment

https://www.cnblogs.com/absfree/p/5415092.html

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>