Java笔记 - 扫描输入

本文主要内容:

1、在这篇文章中,通过Scanner类和JavaSE1.4之前的输入方法对比,为您呈现Scanner的优势。

2、简单介绍了Scanner的常用方法和异常的处理。

3、通过useDelimiter()方法设置定界符和delimiter()返回当前使用的定界符Pattern对象。

4、通过Scanner用正则表达式进行扫描。

5、StringTokenizer的介绍与Scanner和split()方法的对比。

Scanner:

在Java SE1.4之前,从文件或标准输入读取数据是一件很痛苦的事情,一般都是读一行文本,对其进行分词,然后使用Integer,Double等类的各种解析方法来解析数据:

// 使用StringReader将String转换为可读的流对象,然后使用BufferedReader对象封装,使得可以一次读入一行文本
BufferedReader reader = new BufferedReader(new StringReader(“Jason\n23 7”));
try {
System.out.println(“Input your name:”);
String name = reader.readLine();
System.out.println(“name: “ + name);
System.out.println(“How old are you and what’s you favorite number?”);
String line = reader.readLine();
String[] numArr = line.split(“ “);
// 逐个字符串转换解析
int age = Integer.parseInt(numArr[0]);
int num = Integer.parseInt(numArr[1]);
System.out.println(“age: “ + age);
System.out.println(“favorite number: “ + num);
} catch (IOException e) {
e.printStackTrace();
}

输出为:

Input your name:
name: Jason
How old are you and what’s you favorite number?
age: 23
favorite number: 7

在JavaSE5中新增了Scanner类,支持扫描输入,使用起来就非常的方便了:

// 使用StringReader将String转换为可读的流对象,然后使用BufferedReader对象封装,使得可以一次读入一行文本
BufferedReader reader = new BufferedReader(new StringReader(“Jason\n23 7”));
Scanner stdin = new Scanner(reader);
System.out.println(“Input your name: “);
String name = stdin.nextLine();
System.out.println(“name: “ + name);
System.out.println(“How old are you and what’s your favorite number?”);
int age = stdin.nextInt();
int number = stdin.nextInt();
System.out.println(“age: “ + age);
System.out.println(“favorite numver: “ + number);

输出为:

Input your name:
name: Jason
How old are you and what’s your favorite number?
age: 23
favorite numver: 7

Scanner构造器可以接受任何类型的输入对象,如File,InputStream,String,或者Readable对象。所有的基本数据类型都有对应的next方法,包括BigDecimal和BigInteger,普通的next()方法返回下一个String。还有对应的hasNext方法,判断下一个输入分词是否所需的类型。

Scanner在输入结束时会抛出IOException异常,所以Scanner会把IOException吞掉,通过ioException()方法可以找到最近发生的异常,可以使用此方法在必要时进行检查。

Scanner定界符:

默认情况下,Scanner是通过空白字符对输入进行分词的,可以通过useDelimiter方法使用正则表达式指定自己所需的定界符,通过delimiter()方法返回当前正在作为定界符使用的Pattern对象:

Scanner scanner = new Scanner(“1, 2, 3, 4, 5, 6, 7, 8”);
// 使用delimiter()获取当前正在作为定界符的Pattern对象
System.out.println(scanner.delimiter()); // 输出: \p{javaWhitespace}+
while(scanner.hasNext()){
System.out.print(“[“ + scanner.next() + “]“);
}
// 输出: [1,][2,][3,][4,][5,][6,][7,][8]
scanner = new Scanner(“1, 2, 3, 4, 5, 6, 7, 8”);
// 使用useDelimiter()方法来设定自己所需的定界符
scanner.useDelimiter(“\\s,\\s“);
while(scanner.hasNextInt()){
System.out.print(“[“ + scanner.nextInt() + “]“);
}
// 输出: [1][2][3][4][5][6][7][8]

用正则表达式扫描:

除了扫描基本的数据类型,也可以通过Scanner的以下方法:

next

public String next(String pattern)

如果下一个标记与从指定字符串构造的模式匹配,则返回下一个标记。如果匹配操作成功,则扫描器执行与该模式匹配的输入。此方法调用 next(pattern) 的行为与调用 next(Pattern.compile(pattern)) 完全相同。

使用自定义的正则表达式进行扫描,这在扫描复杂数据的时候非常有用,注意,这里仅仅针对下一个输入分词进行匹配,不能跨越两个分词:

String content = “192.168.0.1\n” +
“192.168.0.2\n” +
“192.168.12.34”;
Scanner scanner = new Scanner(content);
String pattern = “(\\d+[.]\\d+[.]\\d+[.]\\d+)”;
// 下面用正则表达式进行扫描
while(scanner.hasNext(pattern)){
scanner.next(pattern);
MatchResult match = scanner.match();
String ip = match.group(1);
// 格式化输出IP
System.out.format(“ip address: %s\n”, ip);
}

StringTokenizer:

这个类在Java引入了正则表达式和Scanner类之后就比较少用到了,在这之前(JavaSE1.4),分割字符串的唯一方法是使用StringTokenizer来分词。而相比之下,前者使用起来更加简单方便,下面是一个使用StringTokenizer进行分词的例子:

// 使用StringTokenizer的方式
String content = “It is raining outside. 外面下着雨…”;
StringTokenizer stoke = new StringTokenizer(content);
while(stoke.hasMoreElements()){
System.out.print(stoke.nextToken() + “ “);
}

// 使用split的方式
System.out.println(Arrays.toString(content.split(“ “)));

// 使用Scanner的方式
Scanner scanner = new Scanner(content);
while(scanner.hasNext()){
System.out.print(scanner.next() + “ “);
}

使用正则表达式和Scanner对象,我们能够更加复杂的模式来分割一个字符串,而StringTOkenizer则比较困难,现在基本上都没有使用这个类了。

arthinking wechat
欢迎关注itzhai公众号
  • 本文作者: arthinking
  • 本文链接: java-notes-scan-input.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!