java - 在内存、处理器、时间方面,Java 中 BufferInputReader、LineNumberReader 和 Stream 之间最好的文件读取器是什么

标签 java stream filereader bufferedinputstream

我尝试了所有三个阅读过程,但无法判断哪个是最好的

内存利用率、处理器使用率、时间复杂度

我在网上看到了很多解决方案,但没有人针对上述条件得出完美的结论。

我尝试了一些方法,请检查代码并让我知道如何使其在上述突出显示的要求中更加优化。

下面是我的代码。

注意: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;
}

}

最佳答案

如果您询问这些类中哪个类速度最快或通常使用最少的内存,那么没有答案。这很大程度上取决于您正在执行的任务。以及如何使用这些类。

如果您要求最快的方法计算文件中的行数,那么最快的方法是使用 InputStream直接读入 ByteBuffer ,然后计算行终止符。这也将使用最少的内存。

原因如下:

  • 任何生成String的东西对于每一行读取都会进行大量不必要的复制,并生成大量垃圾。
  • 任何使用Reader的东西将把字节数据解码为字符数据。这包括 LineNumberReader
  • 如果使用BufferedInputStream并读入一个大的byte[] ,您正在有效地进行自己的(简单)缓冲。您也可以使用InputStream直接。
  • 如果您使用read(byte[])您正在将数据额外复制到 byte[] 中.

有许多教程可以帮助您了解如何使用 ByteBuffer用于快速 I/O。例如:

<小时/>

但是...

在涉及非常大文件的现实应用程序中,性能瓶颈通常是文件系统和存储设备的性能,或者是您对数据进行处理的方式......一旦将数据存储在内存中。

建议避免优化应用程序的 I/O,直到您拥有更高级别的功能,并且能够编写和运行基准测试。然后,您应该分析应用程序以找出瓶颈的真正位置。最后,优化瓶颈。

除非您真的很有经验(而且通常即使您有经验),您关于优化工作最好花在哪里的直觉通常是不正确的。

<小时/>

最后,计算文件行数的最快方法可能是忘记 Java 并使用标准的 native 代码实用程序;例如在 Unix/Linux/MacOS 上使用 wc pathname .

关于java - 在内存、处理器、时间方面,Java 中 BufferInputReader、LineNumberReader 和 Stream 之间最好的文件读取器是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55493965/

相关文章:

java - 通过扫描文件中的数据和特定日期的输出数据来合并不同日期的结果

java - 我如何从 Java 8 中的文本文件中读取特定行?

java - 如何在 Spring RestTemplate 中记录响应?

java - 使用JAX-RS(RESTEasy)作为中间件: brokering a client's request to another server

javascript - 如何将二进制数据从binaryjs转换为字符串/文本

javascript - React DropzoneComponent 在上传之前在本地打开/修改文件

java - 如何从类类型转换为接口(interface)类型

Java 实体管理器 - JSON 阅读器期待一个值但发现 'db'

c# - .NET 中是否有只读流的默认实现?

c# - 在静态方法中管理一次性对象