第十三章 使用Scanner扫描器比使用io流更方便?

 

 

使用Scanner扫描器比使用io流更方便?

使用流读取/写入文件是我最常用的处理方式,今天又新学习了一种使用扫描【Scanner】输入的方法。

对于读取一行文本,对其进行分词【Scanner分词定界符了解更多】,下面这种方式比较麻烦:

1 package 字符串;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.StringReader;
 6 import java.util.Scanner;
 7 
 8 /**
 9  * 扫描输入与使用流读入对比
10  * 
11  * 
12  * @author admin
13  *
14  */
15 public class Scan {
16     
17     public static final String STR = "Sir Robin of Camelot\n22 1.61803  0.897";
18     
19     public static void main(String[] args) {
20         io();
21     }
22 
23     public static void io() {
24         BufferedReader br = new BufferedReader(new StringReader("Sir Robin of Camelot\n22 1.61803  0.897"));
25         try {
26             //读入一行
27             String name = br.readLine();
28             System.out.println(name);
29             
30             //只能一行一行读入,然后再对一行中的数据进行处理
31             String str = br.readLine().replaceAll(" +"," ");
32             System.out.println(str);
33             
34             String[] split = str.split(" ");
35             System.out.println(Integer.parseInt(split[0]));
36             System.out.println(Double.parseDouble(split[1]));
37             System.out.println(Double.parseDouble(split[2]));
38             
39         } catch (IOException e) {
40             e.printStackTrace();
41         }finally {
42             try {
43                 if(br!=null) {
44                     br.close();
45                 }
46             }catch(IOException e) {
47                 e.printStackTrace();
48             }
49         }
50     }
51 
52 }

 

控制台:

Sir Robin of Camelot
22 1.61803 0.897
22
1.61803
0.897

用上面这种方式,你可以看到,如果你想提取一行里的数据,只能使用一些小手段,先将他们分割,然后再取出,在转为你想要的类型,操作代码比较繁琐,而且你还要去处理异常。

 

使用Scanner【java.util.Scanner】扫描器就方便了许多,它的优点看下面代码分析:

 1 package 字符串;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.StringReader;
 6 import java.util.Scanner;
 7 
 8 /**
 9  * 扫描输入与使用流读入对比
10  * 
11  * 
12  * @author admin
13  *
14  */
15 public class Scan {
16     
17     public static final String STR = "Sir Robin of Camelot\n22 1.61803  0.897";
18     
19     public static void main(String[] args) {
20         scan();
21         backUpRead();
22     }
23     
24     
25     @SuppressWarnings("resource")
26     public static void scan() {
27         Scanner scanner = new Scanner(Scan.STR);
28         
29         //nextLine()读取下一行的内容,并且指针向下移动一行
30         System.out.println(scanner.nextLine());//只认换行符,不认我直接换行
31 
32         //nextInt()/nextDouble()指针不会在向下移动,而是水平移动。
33         System.out.println(scanner.nextInt());
34         System.out.println(scanner.nextDouble());
35         System.out.println(scanner.nextDouble());
36         
37         
38         //当找不到本行内下一个值时会抛出异常。找不到下一行时也会抛出异常
39         //System.out.println(scanner.nextDouble());
40         //System.out.println(scanner.nextLine());
41         
42         //Scanner有一个假设,在输入结束时会抛出IOException,所以Sanner会把IOExecption吞掉
43         System.out.println(scanner.ioException());
44     }
45     
46     public static void backUpRead() {
47         Scanner scanner = new Scanner(System.in);
48         
49         System.out.println("你叫什么名字呀?");
50         System.out.println(scanner.next());
51         
52         System.out.println("你家住哪呀?");
53         System.out.println(scanner.next());
54         
55     }
56 
57 }

 

控制台:

Sir Robin of Camelot
22
1.61803
0.897
null
你叫什么名字呀?
毛毛
毛毛
你家住哪呀?
上海
上海

Scanner有许多重载的构造器,所有你想使用的流【文件流,缓存流等等】【这里的流指的是输入流】,都可以在最外层套上扫描器。这样你不仅可以方便的使用readLine()方法,而且对于分词的处理更加方便,从上面代码中也可以看到在使用读取下一行方法next()时以及读取本行内数据nextInt()/nextDouble等方法时并不需要你去写try-catch块。因为Scanner有一个假设,在输入结束时会抛出IOException,所以Scanner会把IOException吞掉【你可以通过ioException()方法,找到最近发生的异常,在必要时刻你可以去检查它】,这样你就没必要每次都去写try-catch块了。想关闭流的话,你可以专门写一个方法,将流对象传入,在这个关闭流对象的方法里将流关闭。

在输入结束时吞掉异常:它并不会吞掉你自己操作导致的异常,就像上面带代码39或40行那样,没有经过hasNextDouble()方法的判断,就直接使用,导致抛出NoSuchElemetmentException异常,它并不会帮你吞掉,所以最好的办法是先判断,在使用。只要不是你非法操作导致的问题,Scanner还是很乐意为您效力的。

 

Scanner套接字节流或字符流:

字节流的套接:在Scanner的构造方法中Scanner(InputStream source),InputStream只要经过适当的套接,总能获得你想要的流接口。

字符流的套接:Scanner(Readable source),你需要使用Java SE5中新加入的一个接口Readable,该接口表示“具有read()方法的某种东西”,查看Readable接口的API你可以发现你想要的带有Reader的类基本都在其中。

 

附:

用正则表达式扫描【不允许你的正则表达式中出现定界符,Scanner默认的定界符也不能出现】:

 1 package 字符串;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.StringReader;
 6 import java.util.Scanner;
 7 import java.util.regex.MatchResult;
 8 import java.util.regex.Matcher;
 9 import java.util.regex.Pattern;
10 
11 /**
12  * 
13  * @author admin
14  *
15  */
16 public class Scan {
17     
18     public static void main(String[] args) {
19         scanByRegex();
20     }
21     
22     public static void scanByRegex() {
23         String str = "58.27.90.129@02/10/2005\n"+
24                     "67.12.20.234@24/07/2006\n";
25         Scanner sc = new Scanner(str);
26         Pattern pattern = Pattern.compile("(\\d+[.]\\d+[.]\\d+[.]\\d+)@(\\d{2}/\\d{2}/\\d{4})");
27         while(sc.hasNext(pattern)) {
28             System.out.println(sc.next(pattern));
29             MatchResult match = sc.match();
30             String ip = match.group(1);
31             String date = match.group(2);
32             System.out.format("Thread on %s from %s\n", date,ip);
33         }
34     }
35 
36 }

控制台:

58.27.90.129@02/10/2005
Thread on 02/10/2005 from 58.27.90.129
67.12.20.234@24/07/2006
Thread on 24/07/2006 from 67.12.20.234

 

posted @ 2018-07-14 14:13  刘呆哗  阅读(586)  评论(0编辑  收藏  举报