手机版
你好,游客 登录 注册
背景:
阅读新闻

Java文件操作类效率对比

[日期:2018-08-25] 来源:cnblogs.com/xiaoxi666  作者:xiaoxi666 [字体: ]

前言

众所周知,Java中有多种针对文件的操作类,以面向字节流和字符流可分为两大类,这里以写入为例:

面向字节流的:FileOutputStream 和 BufferedOutputStream

面向字符流的:FileWriter 和 BufferedWriter

近年来发展出New I/O ,也叫NIO,里面又包装了两个类:NewOutputStream 和 NewBufferedWriter

现在,我们建立测试程序,比较这些类写入文件的性能。

机器配置

  • Processor Name: Intel Core i7
  • Processor Speed: 2.2 GHz
  • Number of Processors: 1
  • Total Number of Cores: 4
  • L2 Cache (per Core): 256 KB
  • L3 Cache: 6 MB
  • Memory: 16 GB

测试程序

纵向比较:几种文件操作类向文件中写入相同行数的内容(每行内容均为“写入文件Data\n”),比较其耗费时间

横向比较:对于同一个文件操作类,比较写入不同行数内容情况下所耗费时间;本文以2的次方指数级增长行数

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

public class testFileIO {

    public static void testDriver () throws IOException {
        int maxlineNum = 100000001;//写入文件的最大行数
        int startlineNum = 1;//写入文件的行数
        int Multiplying = 2;//行数增长倍率

        long begin = 0L;
        long end = 0L;

        //将时间统计写入文件Result.txt中
        FileWriter fileWriter = new FileWriter("./Result.txt", true);
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);

        System.out.println("Test FileOutputStream begin.");
        for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
            begin = System.currentTimeMillis();
            testFileOutputStream(lineNum);
            end = System.currentTimeMillis();
            long timeElapse_FileOutputStream = end - begin;
            bufferedWriter.write(String.valueOf(timeElapse_FileOutputStream)+"\t");
        }
        System.out.println("Test FileOutputStream end.\n");

        System.out.println("Test BufferedOutputStream begin.");
        bufferedWriter.write("\n");
        for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
            begin = System.currentTimeMillis();
            testBufferedOutputStream(lineNum);
            end = System.currentTimeMillis();
            long timeElapse_BufferedOutputStream = end - begin;
            bufferedWriter.write(String.valueOf(timeElapse_BufferedOutputStream)+"\t");
        }
        System.out.println("Test BufferedOutputStream end.\n");

        System.out.println("Test FileWriter begin.");
        bufferedWriter.write("\n");
        for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
            begin = System.currentTimeMillis();
            testFileWriter(lineNum);
            end = System.currentTimeMillis();
            long timeElapse_FileWriter = end - begin;
            bufferedWriter.write(String.valueOf(timeElapse_FileWriter)+"\t");
        }
        System.out.println("Test FileWriter end.\n");

        System.out.println("Test BufferedWriter begin.");
        bufferedWriter.write("\n");
        for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
            begin = System.currentTimeMillis();
            testBufferedWriter(lineNum);
            end = System.currentTimeMillis();
            long timeElapse_BufferedWriter = end - begin;
            bufferedWriter.write(String.valueOf(timeElapse_BufferedWriter)+"\t");
        }
        System.out.println("Test BufferedWriter end.\n");

        System.out.println("Test NewOutputStream begin.");
        bufferedWriter.write("\n");
        for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
            begin = System.currentTimeMillis();
            testNewOutputStream(lineNum);
            end = System.currentTimeMillis();
            long timeElapse_NewOutputStream = end - begin;
            bufferedWriter.write(String.valueOf(timeElapse_NewOutputStream)+"\t");
        }
        System.out.println("Test NewOutputStream end.\n");

        System.out.println("Test NewBufferedWriter begin.");
        bufferedWriter.write("\n");
        for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
            begin = System.currentTimeMillis();
            testNewBufferedWriter(lineNum);
            end = System.currentTimeMillis();
            long timeElapse_NewBufferedWriter = end - begin;
            bufferedWriter.write(String.valueOf(timeElapse_NewBufferedWriter)+"\t");
        }
        System.out.println("Test NewOutputStream end.\n");

        bufferedWriter.close();
    }

    /************************** I/O *****************************/
    //面向字节
    public static void testFileOutputStream (int lineNum) throws IOException {
        FileOutputStream fileOutputStream = new FileOutputStream(new File("./testFileOutputStream.txt"));
        while (--lineNum > 0) {
            fileOutputStream.write("写入文件Data\n".getBytes());
        }
        fileOutputStream.close();
    }

    public static void testBufferedOutputStream (int lineNum) throws IOException {
        FileOutputStream fileOutputStream = new FileOutputStream(new File("./testBufferedOutputStream.txt"));
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
        while (--lineNum > 0) {
            bufferedOutputStream.write("写入文件Data\n".getBytes());
        }
        bufferedOutputStream.close();
    }

    //面向字符
    public static void testFileWriter (int lineNum) throws IOException {
        FileWriter fileWriter = new FileWriter("./testFileWriter.txt");
        while (--lineNum > 0) {
            fileWriter.write("写入文件Data\n");
        }
        fileWriter.close();
    }

    public static void testBufferedWriter (int lineNum) throws IOException {
        FileWriter fileWriter = new FileWriter("./testBufferedWriter.txt");
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        while (--lineNum > 0) {
            bufferedWriter.write("写入文件Data\n");
        }
        bufferedWriter.close();
    }


    /************************** NIO ****************************/
    public static void testNewOutputStream (int lineNum) throws IOException {
        OutputStream outputStream = Files.newOutputStream(Paths.get("./testNewOutputStream.txt"));
        while (--lineNum > 0) {
            outputStream.write("写入文件Data\n".getBytes());
        }
        outputStream.close();
    }

    public static void testNewBufferedWriter (int lineNum) throws IOException {
        BufferedWriter newBufferedReader = Files.newBufferedWriter(Paths.get("./testNewBufferedWriter.txt"));
        while (--lineNum > 0) {
            newBufferedReader.write("写入文件Data\n");
        }
        newBufferedReader.close();
    }


    public static void main (String[] args) throws IOException {
        //多次测试时可清空result.txt文件
        FileWriter fileWriter = new FileWriter("./Result.txt");
        testDriver();
    }
}

测试结果

从上图可以看出,写入行数超过20W以上时,FileOutputStream和NewOutputStream耗费时间远远超出其他4个类。为了清晰,让我们放大其他4个类的图:

 

可以看出,这4个类中,BufferWriter和NewBufferedWriter所耗费时间更少,但总体差别不是很大。

让我们再来看看,写入26W行数据以下时的情况:

     

 可以看出,在数据量较小的情况下,这4个类所耗费时间的差异并不是很大,在更小的数据量下,它们的效率几乎没有差别。

后记

从以上分析可知(注意横坐标写入行数是指数级增加的),各个类的时间复杂度大致为O(1/kn),其中不同的类的k不同,导致了最终巨大的差异。

这里只给出了测试结果,并未分析其底层实现原理,欢迎评论区留言。

另外,我没有在其他机器测试,有兴趣的小伙伴可以将自己的测试结果发出来,共同进步^_^

附件

本次测试数据结果(若看不清,可以下载到本地看)

 

linux
相关资讯       Java文件操作类 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款