比 Scanner 或 BufferedReader 从 STDIN 读取多行数据更快的方式?

Posted

技术标签:

【中文标题】比 Scanner 或 BufferedReader 从 STDIN 读取多行数据更快的方式?【英文标题】:Faster way than Scanner or BufferedReader reading multiline data from STDIN? 【发布时间】:2011-07-07 12:50:56 【问题描述】:

注意:我目前正在使用 java 进行编码。我希望将输入数据读入一个字符串,一次一行(或更多行),我希望总行数很多。

现在我已经实现了

scanner in = new Scanner(System.in)
while (in.hasNextLine()) 
    separated = in.nextLine().split(" ");
    ...

因为在行内我的输入是空格分隔的。

不幸的是,这个过程有数百万行,非常慢,而且扫描仪占用的时间比我的数据处理时间还要多,所以我查看了 java.io 库,发现了很多可能性,但我不确定是哪一个使用(ByteArrayInputStreamFileInputStreamBufferedInputStreamPipedInputStream)。我应该使用哪一个?

要指定,我的数据是从文本文件中输入的,每行有 4 或 6 个以换行符结尾的单词,我需要一次分析一行,设置(4 或 6)个单词到我可以临时管理的数组。 数据格式:

392903840 a c b 293 32.90
382049804 a c 390
329084203 d e r 489 384.90
...

有没有一种方法可以让扫描仪一次读取 1000 条左右的行并变得高效,或者我应该使用这些数据类型中的哪一种(以最小化速度)?

旁注:在实验中我尝试过:

java.io.BufferedReader stdin = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
while(in.ready())
    separated = in.readLine().split(" ");
    ...

哪个效果很好,只是想知道哪个效果最好,以及是否有任何方法可以一次将 100 行读入数据然后处理所有内容。寻找最佳解决方案的选项太多。

【问题讨论】:

【参考方案1】:

你应该用BufferInputStream 包裹你的System.in,比如:

BufferedInputStream bis = new BufferedInputStream(System.in);
Scanner in = new Scanner(bis);

因为这样可以最大限度地减少对 System.in 的读取量,从而提高效率(BufferedInputStream)。

另外,如果您只是读取行,则不需要扫描器,而是需要读取器(具有 readLine()ready() 方法来获取新行并查看是否还有更多数据需要阅读)。

您可以这样使用它(参见java6 : InputStreamReader 的示例):

(我在BufferedReader 中添加了 32MB 的缓存大小参数)

BufferedReader br = new BufferedReader(new InputStreamReader(System.in), 32*1024*1024);
while (br.ready()) 
    String line = br.readLine();
    // process line

来自 InputStreamReader 文档页面:

没有缓冲,每次调用 read() 或 readLine() 可能会导致字节 从文件中读取,转换 变成字符,然后返回, 这可能非常低效。

【讨论】:

嗨,丹,这真的很好用。我现在在没有扫描仪的情况下使用它,但仍然浪费了很多时间,因为读取一行似乎需要时间。有没有一种方法可以让我读取Lines(System.in, 1000) 或类似的东西,然后抓住一堆行,因为我希望(大部分时间)如果我还剩下一行,我应该有数十万行?跨度> 您可以为BufferedReader 构造函数提供一个附加参数以提供缓存大小。这样,如果您想一次缓冲大量数据,您可以提供一个非常大的缓冲区,例如 32 MB。

以上是关于比 Scanner 或 BufferedReader 从 STDIN 读取多行数据更快的方式?的主要内容,如果未能解决你的问题,请参考以下文章

JavaI/O:使用InputStreamReader和BufferedReade实现控制器输入输出

第十三章 使用Scanner扫描器比使用io流更方便?

Java 输入:Scanner 或 IOException

Scanner类的next() 和nextLine()的区别

Scanner类的next() 和nextLine()的区别

Scanner类的next() 和nextLine()的区别