扫描仪与 BufferedReader

Posted

技术标签:

【中文标题】扫描仪与 BufferedReader【英文标题】:Scanner vs. BufferedReader 【发布时间】:2011-01-14 22:33:10 【问题描述】:

据我所知,在 Java 中从文件中读取基于字符的数据的两种最常用方法是使用 ScannerBufferedReader。我也知道BufferedReader通过使用缓冲区来有效地读取文件以避免物理磁盘操作。

我的问题是:

Scanner 的性能是否与BufferedReader 一样好? 为什么您会选择Scanner 而不是BufferedReader,反之亦然?

【问题讨论】:

我通常也使用 Scanner 从标准输入中读取('Scanner in = new Scanner(System.in)' 感觉更干净)。不确定这是否实际上效率较低,但由于从 std in 读取是阻塞的,我无法想象 Scanner 的效率会成为问题。 【参考方案1】:

Scanner 用于从流的内容中解析令牌,而BufferedReader 只是读取流并且不进行任何特殊解析。

实际上,您可以将BufferedReader 传递给scanner 作为要解析的字符源。

【讨论】:

BufferedReader 已同步,而 Scanner 未同步,因此由您决定。 我知道这个话题已经过时了,但是当我尝试从 Process 提供的流中获取内容(即捕获外部命令的输出)时,我在使用 BufferedReader 的操作系统中得到了不同的结果。正如separate answer 中所指出的那样,一旦我将代码更改为使用扫描仪,事情就开始表现一致并且符合预期。 @Reuben 但是Scanner 的输入最终依赖于其他东西,很可能是同步的。【参考方案2】:

在当前最新的 JDK6 版本/构建 (b27) 中,Scanner 的缓冲区 (1024 chars) 比 BufferedReader (8192 chars) 的缓冲区更小,但绰绰有余。

至于选择,如果要解析文件,请使用Scanner,如果要逐行读取文件,请使用BufferedReader .另请参阅他们之前链接的 API 文档的介绍性文本。

解析 = 将给定的输入解释为标记(部分)。它能够直接将特定部分作为 int、string、decimal 等返回给您。另请参阅 Scanner 类中的所有 nextXxx() 方法。 阅读 = 哑流。它不断地回馈你所有的角色,如果你想匹配或组成一些有用的东西,你必须手动检查这些角色。但是,如果您无论如何都不需要这样做,那么阅读就足够了。

【讨论】:

不错的一个。感谢您的缓冲提示。一直在寻找它,因为原生读取非常昂贵。 @Asif:解析 = 将给定的输入解释为标记(部分)。它能够直接将特定部分作为 int、string、decimal 等返回给您。另请参阅 Scanner 类中的所有 nextXxx() 方法。阅读=愚蠢的流媒体。它不断地回馈你所有的角色,如果你想匹配或组成一些有用的东西,你必须手动检查这些角色。但是,如果您无论如何都不需要这样做,那么阅读就足够了。 @BalusC 好的,我已经用过了,readInt();readFloat();等等。现在得到了解析的意思。和 BalusC 你能不能给我一点时间在聊天室里只有 10 分钟,我想问一点关于缓冲的,它是如何工作的。 我在 Scanner 的构造函数中包装了什么 BufferedReader?这是个好主意吗? Scanner 的缓冲区将根据模式匹配的需要进行扩展。所以如果你想要一个更大的缓冲区,你只需要调用,例如findWithinHorizon("\\z", 8192),在它上面和之后,它将使用容量为 8192 字符的缓冲区(或整个文件,如果它小于那个)。【参考方案3】:
    BufferedReader 可能会为您提供更好的性能(因为 Scanner 基于 InputStreamReader,请查看源代码)。 哎呀,从它使用 nio 的文件中读取数据。当我针对BufferedReader 测试nio 的性能和nio 的大文件性能时,性能会更好一些。 要从文件中读取数据,请尝试 Apache Commons IO

【讨论】:

【参考方案4】:

我建议使用BufferedReader 来阅读文本。 Scanner 隐藏 IOExceptionBufferedReader 立即抛出它。

【讨论】:

【参考方案5】:

看到这个link,下面是从那里引用的:

BufferedReader 是一个简单的类,旨在有效地从 下属流。通常,由 Reader 发出的每个读取请求都像 FileReader 导致向 底层流。每次调用 read() 或 readLine() 都可以 导致从文件中读取字节,转换为字符,并且 然后返回,这可能非常低效。效率提高 如果 Reader 在 BufferedReader 中被扭曲,则很明显。

BufferedReader 是同步的,因此对 BufferedReader 的读取操作 可以安全地从多个线程中完成。

另一方面,扫描仪内置了更多的奶酪;它 可以做 BufferedReader 可以做的所有事情,并且在同一级别 效率也是如此。但是,除了 Scanner 可以解析 使用常规的基本类型和字符串的底层流 表达式。它还可以使用 您选择的分隔符。它还可以进行前向扫描 忽略分隔符的底层流!

扫描器不是线程安全的,它必须是外部的 同步。

选择使用 BufferedReader 还是 Scanner 取决于代码 你正在写,如果你正在写一个简单的日志阅读器缓冲 读者足够了。但是,如果您正在编写 XML 解析器 Scanner 是更自然的选择。

即使在读取输入时,如果想通过以下方式接受用户输入 行并说只需将其添加到文件中,BufferedReader 就足够了。 另一方面,如果您想接受用户输入作为命令 多个选项,然后打算执行不同的操作 根据指定的命令和选项,扫描仪将适合 更好。

【讨论】:

“另一方面,扫描仪内置了更多的奶酪;它可以做 BufferedReader 可以做的所有事情,并且效率也相同。”不同意,BufferedReader 比 Scanner 快一点,因为 Scanner 会解析输入数据,而 BufferedReader 只是读取字符序列。【参考方案6】:

    BufferedReader 的缓冲内存比 Scanner 大得多。如果您想从流中获取长字符串,请使用BufferedReader,如果您想从流中解析特定类型的令牌,请使用Scanner

    Scanner可以使用自定义分隔符进行tokenize,并将流解析为原始类型的数据,而BufferedReader只能读取和存储String。

    BufferedReader 是同步的,而 Scanner 不是。如果您使用多个线程,请使用 BufferedReader

    Scanner 隐藏 IOException,而BufferedReader 立即抛出它。

【讨论】:

【参考方案7】:

以下答案摘自Reading from Console: JAVA Scanner vs BufferedReader

当从控制台读取输入时,有两个选项可以实现。首先使用Scanner,另一个使用BufferedReader。两者都有不同的特点。这意味着如何使用它。

Scanner 将给定的输入视为令牌。 BufferedReader 只需将输入作为字符串逐行读取。 Scanner 本身就提供解析能力,就像nextInt()nextFloat() 一样。

但是,其他的有什么区别呢?

扫描仪将给定的输入视为令牌。 BufferedReader 作为流线/字符串。 Scanner 使用正则表达式标记化给定输入。使用 BufferedReader 必须编写额外的代码。 BufferedReaderScanner 快 *点没有。 2 Scanner 未同步,BufferedReader 已同步

ScannerJDK 1.5 及更高版本开始提供。

什么时候应该使用 Scanner 或 Buffered Reader?

看看两者的主要区别,一个使用tokenized,另一个使用stream line。当您需要解析功能时,请改用Scanner。但是,我更喜欢BufferedReader。当您需要从文件中读取数据时,请使用BufferedReader,因为它在读取文件时会使用缓冲内存,从而减少物理驱动器的使用。或者您可以使用BufferedReader 作为Scanner 的输入。

【讨论】:

【参考方案8】:

在java中有不同的输入方式,例如:

1) BufferedReader 2) Scanner 3) 命令行参数

BufferedReader 从字符输入流中读取文本,对字符进行缓冲,以便高效读取字符、数组和行。

其中 Scanner 是一个简单的文本扫描器,它可以使用正则表达式解析原始类型和字符串。

如果你正在编写一个简单的日志阅读器,缓冲阅读器就足够了。如果您正在编写 XML 解析器,Scanner 是更自然的选择。

更多信息请参考:

http://java.meritcampus.com/t/240/Bufferedreader?tc=mm69

【讨论】:

【参考方案9】:

我更喜欢Scanner,因为它不会抛出检查异常,因此它的使用会产生更精简的代码。

【讨论】:

【参考方案10】:

主要区别:

    扫描仪

简单的文本扫描器,可以使用正则表达式解析原始类型和字符串。 扫描程序使用分隔符模式将其输入分解为标记,默认情况下匹配空格。然后可以使用各种 next 方法将生成的标记转换为不同类型的值。

例子:

 String input = "1 fish 2 fish red fish blue fish";
 Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
 System.out.println(s.nextInt());
 System.out.println(s.nextInt());
 System.out.println(s.next());
 System.out.println(s.next());
 s.close(); 

打印以下输出:

1
2
red
blue

使用此代码可以生成相同的输出,它使用正则表达式一次解析所有四个标记:

 String input = "1 fish 2 fish red fish blue fish";

 Scanner s = new Scanner(input);
 s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)");
 MatchResult result = s.match();
 for (int i = 1; i <= result.groupCount(); i++) 
     System.out.println(result.group(i));
 
 s.close();

    BufferedReader:

从字符输入流中读取文本,缓冲字符,以便高效读取字符、数组和行。

可以指定缓冲区大小,也可以使用默认大小。对于大多数用途,默认值足够大。

通常,由 Reader 发出的每个读取请求都会导致对底层字符或字节流发出相应的读取请求。因此,建议将 BufferedReader 包裹在 read() 操作可能成本高昂的任何 Reader 周围,例如 FileReaders 和 InputStreamReaders。例如,

BufferedReader in = new BufferedReader(new FileReader("foo.in"));
 

将缓冲来自指定文件的输入。如果没有缓冲,每次调用 read() 或 readLine() 都可能导致从文件中读取字节,转换为字符,然后返回,这可能非常低效。 使用 DataInputStreams 进行文本输入的程序可以通过将每个 DataInputStream 替换为适当的 BufferedReader 来本地化。

使用的来源: https://docs.oracle.com

【讨论】:

【参考方案11】:

BufferedReaderScanner的区别是:

    BufferedReader 读取数据,而 Scanner 解析数据。 您只能使用 BufferedReader 读取字符串,使用 Scanner 您可以读取不同的数据类型,例如 intBufferedReader 早于 Scanner,它是在 JDK 1.1 上添加的,而 Scanner 是在 JDK 5 版本上添加的。 与 Scanner 的 1KB 相比,BufferedReader 的缓冲区大小更大 (8KB)。 BufferedReader 更适合读取长 String 的文件,而 Scanner 更适合读取来自命令提示符的小用户输入。 BufferedReader 是同步的,而 Scanner 不是同步的,这意味着您不能在多个线程之间共享 ScannerBufferedReaderScanner 更快,因为它不需要花时间进行解析。 BufferedReaderScanner 快一些。 BufferedReader 来自java.io 包,而Scanner 来自java.util 包。

根据点我们可以选择我们的选择。

感谢阅读!

【讨论】:

【参考方案12】:

BufferedReaderScanner的区别如下:

    BufferedReader 已同步,但 Scanner 未同步。 BufferedReader 线程安全,但 Scanner 非线程安全。 BufferedReader 缓冲内存较大,但 Scanner 缓冲内存较小。 BufferedReader 更快,但 Scanner 执行速度较慢。 从控制台读取一行的代码:

BufferedReader

InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String st = br.readLine();
       
// You can make the object InputStreamReader object inside the BufferReader method.
BufferReader br = new BufferedReader(InputStreamReader(System.in));
String st = br.readLine();

// You can even inspect the type of the input stream manually by using Parse method which accepts string parameter.
int x = Integer.parseInt(br.readLine());

// Or you can pass the object directly.
int x = Integer.parseInt(st);

扫描仪

Scanner sc = new Scanner(System.in);
String st = sc.nextLine();

【讨论】:

以上是关于扫描仪与 BufferedReader的主要内容,如果未能解决你的问题,请参考以下文章

Sonarqube 与声纳扫描仪

扫描仪与 BufferedReader

SonarQube Runner 与扫描仪

WASP 扫描仪与 iPhone 的通信

HDFS——块扫描与目录扫描

使用手机摄像头作为扫描仪与 GWT?