我尝试了所有三个阅读过程,但是无法判断哪个是最好的
内存利用率,处理器使用率,时间复杂度
我在网上看到了许多解决方案,但没有人能就上述条件得出完美的结论。
我尝试了几件事,请检查代码,让我知道如何在上述突出显示的要求中对其进行优化。
下面是我的代码。
注意:Out.txt是3Gb文本文件
package Reader;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.LineNumberReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;
/*
* Comparing Execution time of BufferInputReader Vs LineNumberReader Vs
Stream
* o/p > Effeciency of BufferInputReader to LineNumberReader is around ::
200%
*
*/
public class LineReaderBufferInputStream {
public static void main(String args[]) throws IOException {
//LineReaderBufferInputStream
LineReaderBufferInputStream lr = new LineReaderBufferInputStream();
long startTime = System.nanoTime();
int count = lr.countLinesUsingLineNumberReader("D://out.txt");
long endTime = System.nanoTime();
long c1 = (endTime - startTime);
System.out.println(count + " LineReaderBufferInputStream Time taken:: " + c1);
startTime = System.nanoTime();
count = countLinesByBufferIpStream("D://out.txt");
endTime = System.nanoTime();
long c2 = (endTime - startTime);
System.out.println(count + " BufferedInputStream Time taken:: " + c2);
System.out.println("Effeciency of BufferInputReader to LineNumberReader is around :: " + (c1) / c2 * 100 + "%");
// Java8 line by line reader
//read file into stream, try-with-resources
startTime = System.nanoTime();
long cn = countLinesUsingStream("D://out.txt");
endTime = System.nanoTime();
System.out.println(cn +" Using Stream :: " + (endTime - startTime));
}
public int countLinesUsingLineNumberReader(String filename) throws IOException {
LineNumberReader reader = new LineNumberReader(new FileReader(filename));
int cnt = 0;
String lineRead = "";
while ((lineRead = reader.readLine()) != null) {
//if you need to do anything with lineReader.
}
cnt = reader.getLineNumber();
reader.close();
return cnt;
}
public static int countLinesByBufferIpStream(String filename) throws IOException {
InputStream is = new BufferedInputStream(new FileInputStream(filename));
try {
byte[] c = new byte[1024];
int count = 1;
int readChars = 0;
boolean empty = true;
while ((readChars = is.read(c)) != -1) {
empty = false;
for (int i = 0; i < readChars; ++i) {
if (c[i] == '\n') {
++count;
}
}
}
return (count == 0 && !empty) ? 1 : count;
} finally {
is.close();
}
}
public static long countLinesUsingStream(String fileName) throws IOException{
try (Stream<String> streamReader = Files.lines(Paths.get("D://out.txt"))) {
return streamReader.count();
} catch (IOException e) {
e.printStackTrace();
}
return 0;
}
}
答案 0 :(得分:1)
如果您要问这些类中哪一个是最快的或一般使用最少的内存 ,则没有答案。这主要取决于您正在执行的任务。以及使用类的方式。
如果您要求最快的方式来 just 对文件中的行进行计数,那么最快的方式将是使用InputStream
直接读入ByteBuffer
,然后计算行终止符。这也将占用最少的内存。
这是为什么:
String
的内容都会进行很多不必要的复制,并且会产生大量垃圾。Reader
的东西都会将字节数据解码为字符数据。其中包括LineNumberReader
BufferedInputStream
并读入较大的byte[]
,则实际上是在做自己的(简单)缓冲。您也可以直接使用InputStream
。read(byte[])
,则是将数据额外复制到byte[]
中。有许多教程可以帮助您了解如何使用ByteBuffer
进行快速I / O。例如:
但是...
在涉及大型文件的现实应用程序中,性能瓶颈经常被证明是文件系统和存储设备的性能,或者是处理数据以处理数据的方式……一旦将其存储在内存中。
在您可以使用更高级别的功能并且可以编写和运行基准测试之前,最好避免应用程序的I / O优化。然后,您应该对应用程序进行概要分析,以找出瓶颈所在。最后,优化瓶颈。
除非您真的有经验(而且即使是您也是如此),否则您对于将最佳精力花在哪里的直觉通常是不正确的。
最后,计算文件中行数的最快方法可能是忘记Java并使用标准的本机代码实用程序。例如在Unix / Linux / MacOS上,请使用wc pathname
。
答案 1 :(得分:0)
备注:最好明确传递可移植文件的编码,因为默认编码可能会有所不同。
从二进制文件数据到Unicode字符串的较早默认编码是平台编码。
较新的Files.lines
默认使用UTF-8(欢呼)。
这意味着UTF-8的转换速度较慢,并且由于UTF-8多字节序列需要正确的位格式,因此错误的非ASCII字符容易出错。
通常Files.lines
和其他Files.newBufferedReader
都足够快。
对于大文件,可以使用ByteBuffer / CharBuffer,这是通过FileChannel进行的内存映射文件。只需在网上搜索。增益不是那么大。
使用(Buffered)InputStream / ByteBuffer进行不转换比转换为文本要快。
Java将(Unicode)文本存储在字符串中,作为char
的2字节数组。最新的Java可以将其另存为单字节编码(jvm选项),这样可以节省内存。
可能最好压缩文本,例如压缩Out.txt.gz
。用磁盘速度交换CPU。