据我所知,在Java中从文件中读取基于字符的数据的两种最常见的方法是使用Scanner或BufferedReader。我还知道BufferedReader通过使用缓冲区来避免物理磁盘操作,从而有效地读取文件。
我的问题是:
扫描器的性能和BufferedReader一样好吗? 为什么你会选择扫描器而不是BufferedReader,反之亦然?
据我所知,在Java中从文件中读取基于字符的数据的两种最常见的方法是使用Scanner或BufferedReader。我还知道BufferedReader通过使用缓冲区来避免物理磁盘操作,从而有效地读取文件。
我的问题是:
扫描器的性能和BufferedReader一样好吗? 为什么你会选择扫描器而不是BufferedReader,反之亦然?
当前回答
Scanner用于解析来自流内容的令牌,而BufferedReader只读取流,不做任何特殊的解析。
事实上,您可以将BufferedReader传递给扫描器作为要解析的字符源。
其他回答
下面的答案来自从控制台读取:JAVA Scanner vs BufferedReader
当从控制台读取输入时,有两个选项可以实现这一点。首先使用Scanner,另一个使用BufferedReader。两者都有不同的特点。这意味着如何使用它的差异。
扫描器将给定的输入作为标记处理。BufferedReader只是将输入作为字符串逐行读取。Scanner本身提供了解析功能,就像nextInt()、nextFloat()一样。
但是,别人又有什么区别呢?
扫描器将给定的输入作为标记处理。BufferedReader作为流行/字符串。 使用正则表达式对给定输入进行扫描器标记化。使用BufferedReader必须编写额外的代码。 BufferedReader比Scanner更快。2 扫描仪未同步,BufferedReader已同步
从JDK 1.5及更高版本开始就有了Scanner。
什么时候应该使用扫描器,还是缓冲阅读器?
看看它们之间的主要区别,一个使用标记化,另一个使用流线。当您需要解析功能时,请改用Scanner。但是,我更喜欢BufferedReader。当您需要从文件中读取数据时,请使用BufferedReader,因为它在读取文件时使用缓冲内存,从而减少物理驱动器的使用。或者你可以使用BufferedReader作为Scanner的输入。
在当前最新的JDK 18发布/构建(b37)中,与BufferedReader(8192个字符)相比,Scanner的缓冲区更小(1024个字符),但这已经足够了。
至于选择,如果你想解析文件,使用Scanner,如果你想逐行读取文件,使用BufferedReader。也请参阅前面链接的API文档的介绍文本。
解析=将给定的输入解释为标记(部分)。它可以直接返回特定的部分,如int,字符串,小数等。请参见Scanner类中的所有nextXxx()方法。 阅读=无声流媒体。它不断返回给你所有的字符,你反过来必须手动检查,如果你想匹配或组合一些有用的东西。但如果你不需要这样做,那么阅读就足够了。
主要区别:
扫描仪
简单的文本扫描器,可以解析基本类型和字符串使用正则表达式。 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();
BufferedReader:
从字符输入流中读取文本,缓冲字符,以便有效地读取字符、数组和行。 可以指定缓冲区大小,也可以使用默认大小。默认值对于大多数目的来说足够大。
一般来说,对Reader发出的每个读请求都会导致对底层字符或字节流发出相应的读请求。因此,建议将BufferedReader包装在read()操作代价较高的Reader周围,例如filereader和inputstreamreader。例如,
BufferedReader in = new BufferedReader(new FileReader("foo.in"));
将缓冲来自指定文件的输入。在没有缓冲的情况下,每次调用read()或readLine()都可能导致从文件中读取字节,将其转换为字符,然后返回,这可能非常低效。 使用DataInputStreams进行文本输入的程序可以通过用适当的BufferedReader替换每个DataInputStream进行本地化。
来源:https://docs.oracle.com
我建议使用BufferedReader来读取文本。扫描器隐藏IOException而BufferedReader立即抛出它。
我更喜欢Scanner,因为它不会抛出检查异常,因此它的使用结果在一个更精简的代码。