【问题标题】:BufferedReader & FileReader read() Performance - Large Text FileBufferedReader & FileReader read() 性能 - 大文本文件
【发布时间】:2019-05-22 23:20:39
【问题描述】:

我正在使用以下 2 段代码来读取一个大文件。

这个使用FileReader

File file = new File("/Users/Desktop/shakes.txt");
FileReader reader = new FileReader(file);

int ch;
long start = System.currentTimeMillis();
while ((ch = reader.read()) != -1) {
    System.out.print((char) ch);
}
long end = System.currentTimeMillis();

以下使用BufferedReader

File file = new File("/Users/Desktop/shakes.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));

int ch;
long start = System.currentTimeMillis();
while ((ch = reader.read()) != -1) {
    System.out.print((char) ch);
}
long end = System.currentTimeMillis();

查看BufferedReader 的文档:

因此,建议将 BufferedReader 包裹在 read() 操作可能成本高昂的任何 Reader 周围,例如 FileReaders 和 InputStreamReaders。如果没有缓冲,每次调用 read() 或 readLine() 都可能导致从文件中读取字节,转换为字符,然后返回,这可能非常低效。

鉴于此文档和 BufferedReader 类的默认缓冲区大小 8192,使用 BufferedReader 读取文件的总时间不应该更快吗?目前,这两段代码在我的机器上运行时间约为 3000 毫秒。但是,如果我在 BufferedReader 中使用“readLine”,性能会大大提高(~200 毫秒)。

对我缺少的东西的想法?难道不期望即使使用 'read()' 方法,BufferedReader 应该提供比从 FileReader 读取更好的性能吗?

【问题讨论】:

    标签: java io bufferedreader filereader


    【解决方案1】:

    使用BufferedReader 确实比只使用 FileReader 更快。

    我在我的机器上执行了您的代码,使用以下文本文件 https://norvig.com/big.txt (6MB)。

    • 初始结果显示的时间大致相同。每个大约 17 秒。
    • 但是,这是因为System.out.print() 是一个瓶颈(在循环内)。如果没有打印,BufferedReader 的结果是 4 倍。 200 毫秒与 50 毫秒。 (与之前的 17 秒相比)

    换句话说,在基准测试时不要使用System.out.print()

    示例

    使用StringBuilder 的改进基准可能如下所示。

    File file = new File("/Users/Desktop/shakes.txt");
    FileReader reader = new FileReader(file);
    
    int ch;
    StringBuilder sb = new StringBuilder();
    long start = System.currentTimeMillis();
    while ((ch = reader.read()) != -1) {
        //System.out.print((char) ch);
        sb.append((char) ch);
    }
    long end = System.currentTimeMillis();
    
    System.out.println(sb);
    

    上面的代码提供了相同的输出,但执行速度要快得多。使用BufferedReader时,它将准确显示速度差异。

    【讨论】:

    • 感谢 J.A.P 的回答!我修改了我的代码以摆脱 System.out 和 BufferedReader 确实始终比 FileReader 好,而且每次也几乎相同的因素。
    【解决方案2】:

    对我缺少的东西的想法?

    BufferedReader 一次读取一个字符应该比FileReader 更快。 (按数量级!)所以我怀疑问题出在你的基准测试中。

    1. 您的基准测试正在测量读取文件和将其写入标准输出。所以基本上,你的性能数据会被写入文件的开销所扭曲。如果您的输出被写入“控制台”,那么这些开销包括将字符绘制到屏幕......和滚动的开销。

    2. 您的基准测试没有考虑虚拟机启动开销。

    3. 您的基准测试不会(显然)影响文件缓存。 (第一次读取文件时,将从磁盘读取。如果您稍后再次读取,您可能正在从操作系统缓存在内存中的文件副本读取。那会更快。)

    【讨论】:

    • 谢谢斯蒂芬。你是对的,我也可以通过删除 System.out 语句来验证它。
    猜你喜欢
    • 2018-08-04
    • 2018-05-15
    • 2017-12-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2014-05-09
    • 2011-10-06
    • 2014-11-06
    相关资源
    最近更新 更多