扫描输入文本内容
一段程序,可以处理很多类型的数据,因此,在程序开始的阶段,必须要有数据源,简单的情况可以是从控制台输入,也可能是从文本读取,亦或者直接定义字符串读取。
在读取文本内容时,如何进行区分各种数据类型呢?因为文本内容均是以字符串存储,若是以字符串读入,那必定需要进行分词,如下代码所示,比较麻烦:
public class test {
public static BufferedReader input = new BufferedReader(new StringReader("asdjasj 12345 oiw 1.667 wjo ijwq a"));
public static void main(String[] args) {
String str = input.readLine();
//分词
String[] strArray = str.split(" ");
//分别转换
String first = strArry[0];
Integer two = Integer.parseInt(strArray[1]);
Double three = Double.parseDouble(strArray[3]);
}
}
Scanner 类
Java SE5 引入了 Scanner 类来简化扫描输入的负担。
首先,Scanner 类可以以 File 对象、InputStream、String对象和Readable对象作为数据源。
其次,定义好了数据源,就要对数据源进行扫描输入,Scanner中有两类扫描方法,并且各自都有对应各种数据类型的读取方法。
分别是 hasNextXxx() 方法和 nextXxx() 方法,前者判断是否存在,后者获取相应数据。
如下方法:
boolean hasNext(Pattern pattern)
下一段文本与模式匹配,则返回 true。
boolean hasNext(String pattern)
如果下一个文本与指定字符串构造的模式匹配,则返回 true。
boolean hasNextBigDecimal()
如果下一段文本可以解释一个 BigDecimal,则返回 true。
boolean hasNextBigInteger()
如果下一段文本可以解释为一个 BigInteger 值,则返回 true。
boolean hasNextLine()
如果在此扫描器的输入中存在另一行,则返回 true。
--------------我是分割线----------------
String next()
查找并返回来自此扫描器的下一个完整标记。
String next(Pattern pattern)
如果下一个标记与指定模式匹配,则返回下一个标记。
String next(String pattern)
如果下一个标记与从指定字符串构造的模式匹配,则返回下一个标记。
BigDecimal nextBigDecimal()
将输入信息的下一个标记扫描为一个 BigDecimal。
BigInteger nextBigInteger()
将输入信息的下一个标记扫描为一个 BigInteger。
此时,该有一个疑问,Scanner 在扫描读取数据的时候,每次读一个 int 或者 String,而实际文本中是一整串的数据,如何区分呢?其实 Scanner 默认是使用一个空格作为分隔符,当然也可以使用下面这个方法来自定义分隔符:
Scanner useDelimiter(Pattern pattern)
将此扫描器的分隔模式设置为指定模式。
Scanner useDelimiter(String pattern)
将此扫描器的分隔模式设置为从指定 String 构造的模式。
此外,Scanner 在读取数据时没有抛出异常,而真正 IO 流在读写数据时都强制抛出 IOException 异常,这是因为 Scanner 默认抛出该异常时即为输入结束,也就是它把 IOException 在内部处理掉了,当然也可以通过调用方法找到最近发生的异常进行检查:
IOException ioException()
返回此 Scanner 的底层 Readable 最后抛出的 IOException。
下面举个例子在使用 Scanner,使用正则表达式读取特定文本内容,解析后再输出:
public class test {
static String data = "58.24.21.52@02/10/2018\n"+
"58.24.21.52@02/10/2018\n"+
"58.24.21.52@02/10/2018\n"+
"58.24.21.52@02/10/2018\n"+
"58.24.21.52@02/10/2018\n";
public static void main(String[] args) {
Scanner sc = new Scanner(data);
String pattern = "(\\d+[.]\\d+[.]\\d+[.]\\d+)@(\\d{2}/\\d{2}/\\d{4}";
While(sc.hasNext(pattern)) {
sc.next(pattern);
MatchResult match = sc.match();
String ip = match.group(1);
String date = match.group(2);
System.out.format("Threat on %s from %s",date, ip);
}
}
}
在使用正则表达式来匹配时,通过方法match()
来获得匹配结果对象。这里需要注意一点,每次进行匹配的时候只对下一个分词进行匹配,也就是说如果正则表达式中包含了 Scanner 的分隔符,那就一定无法匹配了。