扫描
编程I/O通常涉及转换人们喜欢使用的整齐格式的数据,为了帮助你完成这些工作,Java平台提供了两个API,扫描器API将输入分解为与数据位相关联的单个标记,格式化API将数据组装成格式良好、可读的形式。
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
,此外,数值可以使用数千个分隔符。因此,在美国语言环境中,Scanner
将字符串“32,767”正确地读取为一个整数值。
我们必须提到语言环境,因为千位分隔符和小数符号是特定于语言环境的,因此,如果我们未指定扫描器应使用美国语言环境,则以下示例将无法在所有语言环境中正常运行。这通常不必担心,因为你的输入数据通常来自使用相同语言环境的源,但是这个例子是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
对象,并且该类不提供重写默认语言环境的方法,我们可以覆盖整个程序的语言环境 — 或者我们可以只使用格式化,如下一个主题格式化中所述。