到目前为止,从文件或标准输入读取数据还是一件相当痛苦第事情,一般第解决之道就是读入一行文本,对其进行分词,然后使用Integer Double 等类第各种解析方法来解析数据:
//: strings/SimpleRead.java\
package strings;
import java.io.*;
public class SimpleRead {
public static BufferedReader input = new BufferedReader(
new StringReader("Sir Robin of Camelot\n22 1.61803"));
public static void main(String[] args) {
try {
System.out.println("What is your name?");
String name = input.readLine();
System.out.println(name);
System.out.println(
"How old are you? What is your favorite double?");
System.out.println("(input: <age> <double>)");
String numbers = input.readLine();
System.out.println(numbers);
String[] numArray = numbers.split(" ");
int age = Integer.parseInt(numArray[0]);
double favorite = Double.parseDouble(numArray[1]);
System.out.format("Hi %s.\n", name);
System.out.format("In 5 years you will be %d.\n",
age + 5);
System.out.format("My favorite double is %f.",
favorite / 2);
} catch(IOException e) {
System.err.println("I/O exception");
}
}
} /* Output:
What is your name?
Sir Robin of Camelot
How old are you? What is your favorite double?
(input: <age> <double>)
22 1.61803
Hi Sir Robin of Camelot.
In 5 years you will be 27.
My favorite double is 0.809015.
*///:~
上面的方法只能输入出来简单的情况,如果两个输入值在同一行中,事情就不好办了,我们必须分解这个行才能分别翻译所需要第输入值,利用Scanner类可以大大减轻扫描输入第工作负担:
Scanner的构造器可以接受任何类型的输入,包括FIle对象,InputStream,String或者此类中第Readable对象. Readble表示"具有read()方法的某种东西,BufferedReader也属于这一类.
有了Sacnner,所有的输入,分词以及翻译第操作都隐藏在不同第next方法中,普通第next()方法返回下一个String,所有第基本类型(除char之外)都有对应第next方法,包括BigDecimal和BigInteger,所有第next()方法,只有在找到一个完整第分词之后才会返回.Scannner还有相应第hasNext()方法,用于判断下一个输入分词是否所需类型.
在此例中没有针对IOException添加try块,因为,Scanner有一个假设,在输入结束时会抛出IOException异常,所以Scanner会吧IOException吞掉,不过通过ioException()方法,你可以找到最近发生的异常
//: strings/BetterRead.java
package strings;
import java.util.*;
public class BetterRead {
public static void main(String[] args) {
Scanner stdin = new Scanner(SimpleRead.input);
System.out.println("What is your name?");
String name = stdin.nextLine();
System.out.println(name);
System.out.println(
"How old are you? What is your favorite double?");
System.out.println("(input: <age> <double>)");
int age = stdin.nextInt(); //注意这里没加hasNextInt()方法,如果输入有误程序会抛出异常
double favorite = stdin.nextDouble();
System.out.println(age);
System.out.println(favorite);
System.out.format("Hi %s.\n", name);
System.out.format("In 5 years you will be %d.\n",
age + 5);
System.out.format("My favorite double is %f.",
favorite / 2);//
stdin.ioException().printStackTrace()
}
} /* Output:
What is your name?
Sir Robin of Camelot
How old are you? What is your favorite double?
(input: <age> <double>)
22
1.61803
Hi Sir Robin of Camelot.
In 5 years you will be 27.
My favorite double is 0.809015.
*///:~
用正在表达式扫描
除了能够扫描基本类型之外你还可以使用自定义的正则表达式进行扫描这在扫描复制数据的时候非常有用。下面的例子将扫描一个防火墙日志文件中记录的威胁
package test;
//: strings/ThreatAnalyzer.java
import java.util.regex.*;
import java.util.*;
//import java.io.*; public class ThreatAnalyzer {
static String threatData =
"58.27.82.161@02/10/2005\n" +
"204.45.234.40@02/11/2005\n" +
"58.27.82.161@02/11/2005\n" +
"58.27.82.161@02/12/2005\n" +
"58.27.82.161@02/12/2005\n" +
"[Next log section with different data format]";
public static void main(String[] args) {
Scanner scanner = new Scanner(threatData);
String pattern = "(\\d+[.]\\d+[.]\\d+[.]\\d+)@" +
"(\\d{2}/\\d{2}/\\d{4})"; //注意使用正则表达式中不能含有边界符,否则永远不能匹配成功
while(scanner.hasNext(pattern)) {
scanner.next(pattern);
MatchResult match = scanner.match();
String ip = match.group(1);
String date = match.group(2);
//System.out.printf("2w2%s ",s2);
System.out.format("Threat on %s from %s\n", date,ip); }
}
} /* Output:
Threat on 02/10/2005 from 58.27.82.161
Threat on 02/11/2005 from 204.45.234.40
Threat on 02/11/2005 from 58.27.82.161
Threat on 02/12/2005 from 58.27.82.161
Threat on 02/12/2005 from 58.27.82.161
*///:~