1. Scanner的概述
- 一个可以使用正则表达式来解析基本类型和字符串的简单文本扫描器。
Scanner
使用分隔符模式将其输入分解为标记,默认情况下该分隔符模式与空白匹配。然后可以使用不同的 next 方法将得到的标记转换为不同类型的值。
如:
Scanner sc = new Scanner(System.in); int i = sc.nextInt(); // 使用户能够从 System.in 中读取一个数
通过 myNumbers
文件,遍历文件的文本内容,通过分隔符间隔的词的类型为Long,则将结果存储到aLong变量中:
Scanner sc = new Scanner(new File("myNumbers")); while (sc.hasNextLong()) { long aLong = sc.nextLong(); }
从一个字符串读取若干项:
String input = "1 fish 2 fish red fish blue fish"; Scanner s = new Scanner(input).useDelimiter("\s*fish\s*"); System.out.println(s.nextInt()); System.out.println(s.nextInt()); System.out.println(s.next()); System.out.println(s.next()); s.close(); /* 输出 1 2 red blue */
扫描器所使用的默认空白分隔符通过 Character
.isWhitespace
来识别。不管以前是否更改,reset()
方法将把扫描器分隔符的值重置为默认空白分隔符。
扫描操作可能被阻塞,而等待信息的输入。
2. Scanner的构造方法原理
- Scanner(File source) 从指定文件扫描生成值
- Scanner(File source, String charsetName)
-
Scanner sc = new Scanner(new File("myNumbers"));
-
- Scanner(InputStream source) 从指定的输入流扫描生成值
- Scanner(InputStream source, String charsetName)
-
Scanner sc = new Scanner(System.in);
- 这种就是从 标准的键盘输入
-
- Scanner(Readable source) 从指定源扫描生成值
- Scanner(ReadableByteChannel source) 从指定信道扫描生成值
- Scanner(ReadableByteChannel source, String charsetName)
- Scanner(String source) 从指定字符串扫描生成值
-
String input = "1 fish 2 fish red fish blue fish"; Scanner s = new Scanner(input).useDelimiter("\s*fish\s*");
-
Scanner获取数据出现的小问题以及解决方案:
- 常用方法:
- public int nextInt(); 获取一个int类型的值
- public String nextLine(); 获取一个String类型的值
- 案例演示
- 先演示获取多个int值,多个String值的情况
- 再演示先获取int值,然后获取String值出现问题
-
package com.heima.scanner; import java.util.Scanner; public class Demo2_Scanner { public static void main(String[] args) { Scanner sc = new Scanner(System.in); // 连续输入两个整数,int类型 /*System.out.println("请输入第一个整数:"); int i = sc.nextInt(); System.out.println("请输入第二个整数:"); int j = sc.nextInt(); System.out.println("i = " + i + ", j = " + j);*/ // 连续输入两个字符串,String类型 /*System.out.println("请输入第一个字符串:"); String line1 = sc.nextLine(); System.out.println("请输入第二个字符串:"); String line2 = sc.nextLine(); System.out.println("line1 = " + line1 + ", line2 = " + line2);*/ System.out.println("请输入第一个整数:"); int i = sc.nextInt(); System.out.println("请输入第二个字符串:"); String line2 = sc.nextLine(); System.out.println("i = " + i + ", line2 = " + line2); /* * 输出: 请输入第一个整数: 11 请输入第二个字符串: i = 11, line2 = 出错情况:输入第一个整数后,没有直接等待键盘输入的第二个字符串,直接输出了拼接结果。 出错原因分析: nextInt() 是键盘录入整数的方法。 当我们录入11的时候,其实在键盘上录入的是10和 ,nextInt()方法只获取10就结束了。 nextLine() 是键盘录入字符串的方法,可以接收任意类型,但是,它凭什么能获取一行呢? 通过 ,只要遇到 就证明一行结束。 */ } }
- 问题解决方案:
- 第一种:先获取一个数值后,再创建一个新的键盘录入对象获取字符串
- 创建两次对象,但是浪费空间
- 第二种:把所有的数据先按照字符串获取,然后要什么,就对应转换为什么
- 第一种:先获取一个数值后,再创建一个新的键盘录入对象获取字符串
3. 一般方法
- close() 关闭扫描器
- hasNext() 如果此扫描器的输入中有另一个标记,则返回 true。
- hasNext(Pattern pattern) 如果下一个完整标记与指定模式匹配,则返回 true。
- hasNextInt() 如果通过使用
nextInt()
方法,此扫描器输入信息中的下一个标记可以解释为默认基数中的一个 int 值,则返回 true。 nextInt() 将输入信息的下一个标记扫描为一个 int。
nextLine() 此扫描器执行当前行,并返回跳过的输入信息。
next()
和 hasNext()
方法及其基本类型 companion 方法(如 nextInt()
和 hasNextInt()
)首先跳过与分隔符模式匹配的输入,然后尝试返回下一个标记。
在等待更多输入时 hasNext 和 next 方法都可能阻塞。
hasNext 方法是否阻塞与其相关的 next 方法是否阻塞无关。
findInLine(java.lang.String)
、findWithinHorizon(java.lang.String,int)
和 skip(java.util.regex.Pattern)
方法的执行与分隔符模式无关。
这些方法会尝试匹配与输入中的分隔符无关的指定模式,因此可用于分隔符无关的特殊环境中。在等待更多输入时这些方法可能阻塞。
当某一扫描器抛出 InputMismatchException
时,该扫描器不会传递导致该异常的标记,因此可以通过其他某种方法来获取或跳过它。
对于某些类型的分隔模式,可能返回空标记。例如,"\s+" 模式不会返回空标记,因为它与该分隔符的多个实例匹配。而分隔模式 "\s" 可能返回空标记,因为它一次只传递一个空格。
扫描器可以从实现 Readable
接口的任何对象读取文本。如果对底层 readable 的 Readable.read(java.nio.CharBuffer)
方法的调用抛出 IOException
,则扫描器认为已经到达了输入的结尾。底层 readable 最新抛出的 IOException 可以通过 ioException()
方法获取。
如果 Scanner
关闭,且其输入源实现 Closeable
接口,则该输入源也将关闭。
若没有外部同步,则 Scanner
的多线程使用是不安全的。
除非另行说明,否则将一个 null
参数传递到 Scanner
的任何一个方法中都将抛出 NullPointerException
。
默认情况下扫描器会将数字解释为十进制形式,除非已经使用 useRadix(int)
方法设置了不同的基数。不管以前是否更改,reset()
方法将把扫描器的基数重置为10
。