Scanner

1.Scanner是什么?常用方法有哪些?

Scanner是JDK5的新特性,一个可以使用正则表达式来解析基本类型和字符串的简单文本扫描器

Scanner只是用来扫描文本的一个扫描器,也就是说,它与 文本的关系 是它扫描文本

Scanner可以从字符串、文件、标准输入流中扫描数据,由构造方法指定扫描的数据源

我们常用的 new Scanner(System.in)就是从输入流中扫描数据。

所以,Scanner的作用并不只是接收键盘输入。

 

常用方法:

  nextInt();//将输入信息的下一个标记扫描为一个 int

  next();//查找并返回来自此扫描器的下一个完整标记

 

2.有了Scanner才能键盘输入吗?

Scanner提供了一系列的构造方法,其中 new Scanner(System.in) 可以接收标准输入流输入也就是键盘输入

但其实,没有Scanner也能在控制台输入

 

我们可以写一个简单的HelloWorld程序,打上断点在IDE里以debug模式运行,只要程序开始运行没有结束,就可以在控制台随便输入 

1 public class HelloWorld {
2     public static void main(String[] args) {
3         System.out.println("Hello,world!");
4     }
5 }

在第3行打上断点,以debug模式运行

123            //运行开始,在控制台可以用键盘输入
Hello,world!   //走下一步,在控制台打印出 "Hello,world!"
456       //此时程序未结束,可以继续在控制台输入

而程序运行前和结束后,都是无法在控制台上输入数据的

 

实际上,从程序运行起来,到运行结束的这段时间,都可以在控制台输入

一般程序没有阻塞,所以直接就运行结束了

而Scanner可以将键盘输入接收,通过next方法获取到键盘输入

 

网上有说 从new Scanner的时候开始,控制台开始接收键盘输入,这是不正确的

键盘输入什么时候都可以

 

 

3.Scanner阻塞

创建Scanner对象并不会导致程序阻塞

Scanner的一些方法,比如hasNextInt()等hasNext方法,以及nextInt()等next方法可能会导致程序阻塞

 

API上是这么说的

扫描操作可能被阻塞,而等待信息的输入。

next() 和 hasNext() 方法及其基本类型 companion 方法(如 nextInt() 和 hasNextInt())首先跳过与分隔符模式匹配的输入,然后尝试返回下一个标记。在等待更多输入时 hasNext 和 next 方法都可能阻塞。hasNext 方法是否阻塞与其相关的 next 方法是否阻塞无关。 

 

hasNext之类的方法是判断下一个标记是否是某个类型,若没有下一个标记时程序会阻塞,等待键盘输入

 next()、nextInt()、nextDouble()等方法可能会发生阻塞,是因为Scanner对象创建好后,如果没有扫描到有效输入,会持续等待直到有有效输入为止

但是hasNext方法与next方法有一个很大的区别是,hasNext不会移动cursor,next方法会移动cursor

 

 

4.Scanner扫描器如何扫描? 

Scanner 使用分隔符模式将其输入分解为标记,默认情况下该分隔符模式与空白匹配。然后可以使用不同的 next 方法将得到的标记转换为不同类型的值。 

 注意空白不是空格

 

两个分隔符之间的内容为一个完整的标记

 

默认情况下分隔符模式与空白匹配,如

1 public static void demo1() {
2     Scanner s = new Scanner(System.in);
3     while(s.hasNext()){
4         System.out.println(s.next());
5     }
6 }
输入:  2      e   3
输出:
2
e
3

 

以debug模式运行main方法,在创建Scanner对象前在控制台在输入如下数据,然后放行,会发现程序没有阻塞,直接运行结束。

 1 public static void main() {
 2     Scanner sc = new Scanner(System.in);
 3     System.out.println("请输入一个字符串");
 4     String s = sc.next();
 5     System.out.println(s);
 6     System.out.println("请输入一个字符串");
 7     s = sc.nextLine();
 8     System.out.println(s);
 9     sc.close();
10 }
abc defg hijk
1 234 56
请输入一个字符串
abc
请输入一个字符串
 defg hijk

  

也可以在cmd窗口运行,如下

请输入一个字符串
 123 456 789
123
请输入一个字符串
 456 789  

第一次输入的时候输入 123 456 789

第二次不用输入直接可以读取到 456 789

 

由此可见,Scanner扫描器是从一开始进行扫描,与Scanner对象创建的位置无关

 

 

首先用键盘输入,按下回车之后,这就是一个完整的输入,以上例子为   

 123 456 789

然后Scanner根据默认分隔符空白将输入分解为一个个的标记,也就是 123、456、789

 

Scanner扫描流程:

 

 

5.Scanner使用useDelimiter()方法指定分隔符

指定分隔符为空格

1 public static void demo2() {
2     Scanner s = new Scanner(System.in);
3     s.useDelimiter(" ");
4     while(s.hasNext()){
5         System.out.println(s.next());
6     }
7 }
输入:(2,e,3前面的空格数分别为2、3、4,3后面没有空格)
  2   e    3
输出:(2前面有1个空行,e前面有2个空行,3没有输出)

2


e


 

两个分隔符即两个空格之间的为一个标记

因为3后面没有空格,所以它不是一个完整的标记

 

 

继续在控制台输入 q ,按下回车,仍然没有输出,这是因为没有空格分隔符,扫描器仍然在等待输入

输入空格后,再按回车就可以在控制台输出了

全部输出如下:

2


e



q
 
3
q

  

 

指定分隔符为逗号

1 public static void main(String[] args) {
2     Scanner sc = new Scanner(System.in);
3     sc.useDelimiter(",");
4     while(sc.hasNext()) {
5         String line = sc.next();
6         System.out.println(line);
7     }
8 }

第一行为键盘输入,下面的为输出

点击回车的时候,Scanner就会按照分隔符,将键盘输入分解为一个个的标记(也就是下面控制台输出的那些),然后调用next方法按照指定类型一个一个去扫描

 

 

 

6.使用hasNext方法时出现死循环问题

如下程序:

 1 public static void demo1() {
 2     Scanner sc = new Scanner(System.in);
 3     while(true) {
 4         System.out.println("请输入一个整数:");
 5         if(sc.hasNextInt()) {
 6             System.out.println("输入的整数是:"+sc.nextInt());
 7         }else {
 8             System.out.println("输入错误!请重新输入!");
 9         }
10     }
11 }

运行结果:

请输入一个整数:
3244
输入的整数是:3244
请输入一个整数:
sd
输入错误!请重新输入!
请输入一个整数:
输入错误!请重新输入!
请输入一个整数:
输入错误!请重新输入!
请输入一个整数:
输入错误!请重新输入!
…………

 

如输出所示,当输入类型不是整数即sc.hasNextInt()为false的时候,会出现死循环

而出现这个问题的原因是,sc.hasNextInt()只是判断读取器的下一个标记是否为int类型,并不会去移动cursor

当输入为整数时,调用了sc.nextInt()移动了cursor,所以扫描器可以扫描下一个输入

当输入不是整数时,cursour没有移动,故sc.hasNextInt()一直为false,也就一直循环下去了

 

即,hasNext方法扫描器可能阻塞,但此方法不会去移动cursor,所以循环会一直下去。

 

7.是否扫描回车?

next()、nextInt()、nextDouble()等 读取结束后,cursor指向本行,即不读取最后的换行符,若此时再用nextLine()读取则读取到的是回车

nextLine()方法会读取一行,从cursor开始到一行的结尾,包括空格和最后的回车

posted @ 2019-08-27 09:45  绮丽梦境  阅读(683)  评论(0编辑  收藏  举报