本教程适用于JDK 8。本页中描述的示例和实践不利用后续版本引入的改进,并且可能使用不再可用的技术。
有关Java SE 9及其后续版本中更新的语言特性的摘要,请参阅Java语言更改。
有关所有JDK版本的新功能、增强功能和已删除或弃用选项的信息,请参阅JDK发行说明。
类型为Scanner
的对象可用于将格式化输入拆分为标记,并根据它们的数据类型进行翻译。
默认情况下,扫描器使用空白字符来分隔标记。(空白字符包括空格、制表符和行终止符。请参阅Character.isWhitespace
的文档以查看完整列表。)为了了解扫描的工作原理,让我们来看看ScanXan
,这是一个读取xanadu.txt
中每个单词并逐行打印出来的程序。
import java.io.*; import java.util.Scanner; public class ScanXan { public static void main(String[] args) throws IOException { Scanner s = null; try { s = new Scanner(new BufferedReader(new FileReader("xanadu.txt"))); while (s.hasNext()) { System.out.println(s.next()); } } finally { if (s != null) { s.close(); } } } }
注意,在完成对扫描器对象的使用后,ScanXan
调用了Scanner
的close
方法。尽管扫描器不是一个流,但你需要关闭它来表示你已经完成了对其底层流的使用。
ScanXan
的输出如下:
In Xanadu did Kubla Khan A stately pleasure-dome ...
要使用不同的标记分隔符,可以调用useDelimiter()
方法,并指定一个正则表达式。例如,假设你希望标记分隔符为逗号,后面可以跟随空白字符。你可以调用:
s.useDelimiter(",\\s*");
ScanXan
示例将所有输入标记视为简单的String
值。Scanner
还支持Java语言的所有基本类型(除了char
),以及BigInteger
和BigDecimal
。此外,数值可以使用千位分隔符。因此,在US
区域设置中,Scanner
会正确地将字符串"32,767"解读为表示整数值。
我们必须提到区域设置,因为千位分隔符和小数符号是区域设置特定的。因此,如果我们没有指定扫描器应使用US
区域设置,以下示例在所有区域设置下都无法正常工作。通常情况下,你无需担心这个问题,因为输入数据通常来自与你相同的区域设置的来源。但是这个示例是Java教程的一部分,会在全球范围内分发。
这个例子是一个ScanSum
示例,它读取一个double
值的列表并将它们相加。以下是源代码:
import java.io.FileReader; import java.io.BufferedReader; import java.io.IOException; import java.util.Scanner; import java.util.Locale; public class ScanSum { public static void main(String[] args) throws IOException { Scanner s = null; double sum = 0; try { s = new Scanner(new BufferedReader(new FileReader("usnumbers.txt"))); s.useLocale(Locale.US); while (s.hasNext()) { if (s.hasNextDouble()) { sum += s.nextDouble(); } else { s.next(); } } } finally { s.close(); } System.out.println(sum); } }
这是样本输入文件:usnumbers.txt
8.5 32,767 3.14159 1,000,000.1
输出的字符串是"1032778.74159"。在某些区域设置中,句号可能是其他字符,因为System.out
是一个PrintStream
对象,该类不提供覆盖默认区域设置的方法。我们可以为整个程序覆盖区域设置,或者可以使用格式化,如下一个主题格式化中所述。