我正在使用以下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读取文件的总时间是否应该更快?目前,这两段代码都在我的计算机上运行〜3000ms。但是,如果我在BufferedReader中使用'readLine',则性能会大大提高(〜200ms)。
对我所缺少的东西有什么想法?难道不希望即使使用'read()'方法,BufferedReader的性能也要比从FileReader读取的性能更好吗?
答案 0 :(得分:2)
使用BufferedReader
确实比仅使用FileReader更快。
我在计算机上使用以下文本文件https://norvig.com/big.txt(6MB)执行了您的代码。
System.out.print()
是瓶颈(在循环内)。如果不打印,使用BufferedReader
的结果快4倍。 200ms与50ms。 (与之前的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
时,它将准确显示速度差异。
答案 1 :(得分:0)
对我所缺少的东西有什么想法?
一次从BufferedReader
读取文件字符应该比FileReader
更快。 (数量级!)所以我怀疑问题出在您的基准测试中。
您的基准测试正在衡量读取文件并将其写入标准输出的能力。因此,基本上,写入文件的开销会使您的性能数字失真。并且,如果将输出写入“控制台”,则这些开销包括将字符绘制到屏幕上并进行滚动的开销。
您的基准测试不考虑虚拟机启动开销。
您的基准测试(显然)没有起到文件缓存的作用。 (第一次读取文件时,将从磁盘读取该文件。如果不久之后再次读取该文件,则可能是 从操作系统缓存在内存中的文件副本中读取。会更快。)