可以证明,字符串操作是计算机程序设计中最常见的行为。
13.1 不可变String
String对象是不可变的。查看JDK文档你就会发现,String 类中每一个看起来会修改String值的方法,实际上都是创建了一个全新的String对象,以包含修改后的字符串内容。而最初的String对象则丝毫未动。
13.7 扫描输入
到目前为止,从文件或标准输入读取数据还是一件相当痛苦的事情。一般的解决之道就是读入一行文本,对其进行分词,然后使用Integer、Double等类的各种解析方法来解析数据。
/**
* 作者:LKP
* 时间:2018/9/20
*/
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");
}
}
}
运行结果:
input元素使用的类来自java.io。StringReader将String转化为可读的流对象,然后用这个对象来构造BufferReader对象,因为我们要使用BufferReader的readerLine()方法。最终,我们可以使用input对象一次读取一行文本,就像是从控制台读入标准输入一样。
13.7.1 Scanner定界符
在默认的情况下,Scanner根据空白字符对输入进行分词,但是你可以用正则表达式指定自己所需的定界符:
/**
* 作者:LKP
* 时间:2018/9/20
*/
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());
}
}
}
运行结果:
这个例子使用逗号(包括逗号前后任意的空白字符)作为定界符,同样的技术也可以用来读取逗号分隔的文件。我们可以用useDelimiter()来设置定界符,同时,还有一个delimiter()方法,用来返回当前正在作为定界符使用的Pattern对象。
13.7.2 用正则表达式扫描
除了能够扫描基本类型之外,你还可以使用自定义的正则表达式进行扫描,这在扫描复杂数据的时候非常有用。下面的例子将扫描一个防火墙日志文件中记录的威胁数据:
**
* 作者:LKP
* 时间:2018/9/20
*/
public class ThreatAnalyzer {
static String threatData = "28.27.82.151@02/10/2005\n"+
"132.27.82.151@03/10/2005\n"+
"31.27.82.151@04/10/2005\n"+
"32.27.82.151@05/10/2005\n";
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);
}
}
}
运行结果:
当next()方法配合指定的正则表达式使用时,将找到下一个匹配该模式的输入部分,调用match()方法就可以获得匹配的结果。