java编程思想读书笔记 第十三章 字符串(下)

1.扫描输入
从文件或标准输入读取数据的一般解决之道就是读入一行文本,对其进行分词,然后使用Integer、Double等类的各种解析方法来解析数据:

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 : )");
            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 (Exception 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 : <double>)
22 1.61803
Hi Sir Robin of Camelot.
In 5 years you will be 27.
My favorite double is 0.809015.

input元素使用类来自java.io,StringReader将String转化为可读的流对象,然后用这个对象来构造BufferedReader对象,因为我们要使用BufferedReader的readLine()方法。最终,我们可以使用input对象一次读取一行文本,就像是从控制台读入标准输入一样。
不过Java SE5新增了Scanner类(java.util.*),可以接受任何类型的输入对象,包括File对象,InputStream、String或者Readable对象。Readable时Java SE5新增的一个接口,具有read()方法。使用Scanner,所有输入,粉刺,翻译的操作都隐藏在不同类型的next()中,比如nextInt()、nextDouble(),普通的next()方法方法返回下一个String。所有基本类型都有next()方法,除了char类型,包括BigDecimal和BigInteger。Scanner还有相应的hasNext方法,用以判断下一个输入分词是否是所需的类型。Scanner可以自动吞IOException异常。

1.1Scanner定界符
默认情况下,Scanner根据空白字符对输入进行分词,也可以用正则表达式指定定界符,利用函数scanner.useDelimiter(正则表达式):

public class ScannerDelimiter {
public static void main(String[] args) {
Scanner scanner = new Scanner("12, 42, 78, 99, 42");
scanner.useDelimiter("\\s*,\\s*"); //,作为定界符,包括逗号前后的空格符
while(scanner.hasNextInt())
System.out.println(scanner.nextInt());
}
} 
Output:
12
42
78
99
42

这个例子使用逗号作为定界符,同样的技术也可以用来读取逗号分隔的文件。我们可以用useDelimiter()来设置定界符,同时,还有一个delemiter()方法,用来返回当前正在作为定界符使用的Pattern对象。

1.2用正则表达式扫描
除了能够扫描基本类型外,可能还想要扫描自定义的正则表达式。
如下:

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.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

当next()方法配合指定的正则表达式使用时,将找到下一个匹配该模式的输入部分,调用match()方法就可以获得匹配的结果。需要注意的是配合正则表达式扫描时,只针对下一个输入分词,如果正则表达式中含有定界符,则永远不可能匹配成功。

2.StringTokenizer
以前用StringTokenizer来分词,现在有了正则表达式和Scanner,StringTokenizer基本上已经废弃不用了。
3.总结
过去,java对字符串操作的支持相当不完善。不过到目前为止,它对字符串操作的支持已经很完善了。现在在使用字符串的时候还是要在细节上注意效率的问题。

你可能感兴趣的:(java编程思想读书笔记)