ChatGPT解决这个技术问题 Extra ChatGPT

扫描仪与 BufferedReader

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

我的问题是:

Scanner 的性能是否与 BufferedReader 一样好?

为什么你会选择 Scanner 而不是 BufferedReader,反之亦然?

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

r
roottraveller

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

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


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

在当前最新的 JDK 18 发行版/内部版本 (b37) 中,与 BufferedReader (8192 chars) 相比,Scanner 的缓冲区 (1024 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个字符的缓冲区(或者整个文件,如果它小于那个)。
E
Eliran Malka

请参阅此 link,从那里引用以下内容:

BufferedReader 是一个简单的类,旨在有效地从底层流中读取。通常,由 Reader(如 FileReader)发出的每个读取请求都会导致对底层流发出相应的读取请求。每次调用 read() 或 readLine() 都可能导致从文件中读取字节,转换为字符,然后返回,这可能非常低效。如果 Reader 在 BufferedReader 中变形,效率会显着提高。 BufferedReader 是同步的,因此 BufferedReader 上的读取操作可以安全地从多个线程完成。另一方面,扫描仪内置了更多的奶酪。它可以做 BufferedReader 可以做的所有事情,而且效率也相同。但是,除此之外,Scanner 可以使用正则表达式解析基本流的基本类型和字符串。它还可以使用您选择的分隔符标记基础流。它还可以不考虑分隔符对底层流进行前向扫描!然而,扫描器不是线程安全的,它必须是外部同步的。使用 BufferedReader 或 Scanner 的选择取决于您正在编写的代码,如果您正在编写一个简单的日志阅读器,缓冲阅读器就足够了。但是,如果您正在编写 XML 解析器,Scanner 是更自然的选择。即使在读取输入时,如果想逐行接受用户输入并说只是将其添加到文件中,BufferedReader 就足够了。另一方面,如果您想接受用户输入作为具有多个选项的命令,然后打算根据指定的命令和选项执行不同的操作,则 Scanner 将更适合。


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

BufferedReader 的缓冲内存比 Scanner 大得多。如果您想从流中获取长字符串,请使用 BufferedReader,如果您想从流中解析特定类型的令牌,请使用 Scanner。 Scanner 可以使用自定义分隔符使用 tokenize 并将流解析为原始类型的数据,而 BufferedReader 只能读取和存储 String。 BufferedReader 是同步的,而 Scanner 不是。如果您使用多个线程,请使用 BufferedReader。 Scanner 隐藏 IOException 而 BufferedReader 立即抛出它。


r
roottraveller

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


L
Laurel

BufferedReader 和 Scanner 的区别如下:

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

缓冲阅读器:

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();

F
Felierix

BufferedReader 和 Scanner 的区别在于:

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

根据这些点,我们可以选择我们的选择。

谢谢阅读!


F
Felierix

主要区别:

扫描器

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

Scanner 使用分隔符模式将其输入分解为标记,默认情况下匹配空格。然后可以使用各种 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();

缓冲阅读器:

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

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

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

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

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

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


m
manisha mulchandani

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

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

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

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

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

更多信息请参考:

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


F
Felierix

下面的答案来自Reading from Console: JAVA Scanner vs BufferedReader

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

Scanner 将给定的输入视为令牌。 BufferedReader 只需将输入作为字符串逐行读取。 Scanner 本身提供了与 nextInt()nextFloat() 类似的解析功能。

但是,其他人之间有什么区别?

扫描器将给定的输入视为令牌。 BufferedReader 作为流线/字符串。

扫描仪使用正则表达式对给定的输入进行标记。使用 BufferedReader 必须编写额外的代码。

BufferedReader 比 Scanner *point no. 快。 2

Scanner 不同步,BufferedReader 同步

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

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

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


t
thisismydesign

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


F
Felierix

BufferedReader 可能会给您带来更好的性能(因为 Scanner 基于 InputStreamReader,请查看源代码)。哎呀,从它使用 nio 的文件中读取数据。当我针对大文件的 BufferedReader 性能测试 nio 性能时,nio 显示出更好的性能。要从文件中读取数据,请尝试使用 Apache Commons IO。