1. 程式人生 > >System類對IO的支持

System類對IO的支持

方法 分隔 row cep append 一個 file you static

系統輸出

  學完了PrintStream PrintWriter之後我們會發現裏面方法很熟悉,例如:print() println() 實際上在之前使用的系統輸出就利用了IO流模式完成的,在System類中定義有三個操作的常量:

    標準輸出(顯示器):public static final PrintStream out

    錯誤輸出:public static final PrintStream err

    標準輸入(鍵盤):public static final InputStream in

  原來之前使用的System.out.println()一直都屬於IO的操作範疇。

系統輸出

  系統輸出有兩個常量:out err 而且這兩個常量所表示的都是PrintStream類的對象,從Java的設計本質上來講,這樣的兩種輸出有以下的設計目的:out輸出的是希望用戶可以看見內容,err是希望輸出用戶不能看見的內容。

  這兩種輸出在實際的開發之中都沒用。

 1 package cn.Tony.demo;
 2 
 3 public class TestDemo{
 4     public static void main(String[] args) throws Exception {
 5         try {
 6             Integer.parseInt("abc");
7 }catch(Exception e) { 8 System.err.println(e); 9 System.out.println(e); 10 } 11 12 } 13 }

  System.err也只是作為一個保留的屬性提供存在。System.out屬於PrintStream,屬於OutputStream

範例:

 1 package cn.Tony.demo;
 2 
 3 import java.io.OutputStream;
 4 
 5
public class TestDemo{ 6 public static void main(String[] args) throws Exception { 7 OutputStream out=System.out; 8 out.write("世界和平".getBytes()); 9 } 10 }

  抽象類不同的子類針對同一方法有不同的實現,用戶調用的時候的核心參考的就是OutputStream。

系統輸入 in

  System.in對於的類型是InputStream,而這種的輸入流指的是由用戶通過鍵盤進行輸入(用戶輸入),java本身並沒有這種直接的用戶輸入處理,如果要想實現這種輸入處理必須用java.io的模式完成

範例:利用InputStream

 1 package cn.Tony.demo;
 2 
 3 import java.io.InputStream;
 4 
 5 public class TestDemo{
 6     public static void main(String[] args) throws Exception {
 7         InputStream input=System.in;//為父類實例化
 8         byte data[]=new byte[1024];//開辟一個空間
 9         System.out.println("請輸入信息:");
10         int temp=input.read(data);//數據讀取到字節數組中
11         System.out.println("【ECHO】輸入內容:"+new String(data,0,temp));
12         
13     }
14 }

  現在發現當用戶輸入數據的時候需要暫停執行,也就是說程序進入到阻塞狀態,直到用戶輸入完成(按下回車),那麽才能向下執行,但是以上的程序本身有一個致命的問題,那麽核心點就在於:要開辟的字節數組的長度是固定的,輸入內容超過了該長度。如果開辟的量超過長度,只能接受部分數據,保存內存流,

 1 package cn.Tony.demo;
 2 
 3 import java.io.ByteArrayOutputStream;
 4 import java.io.InputStream;
 5 
 6 public class TestDemo{
 7     public static void main(String[] args) throws Exception {
 8         InputStream input=System.in;//為父類實例化
 9         ByteArrayOutputStream bos=new ByteArrayOutputStream();
10         byte data[]=new byte[1024];//開辟一個空間
11         System.out.println("請輸入信息:");
12         int temp=0;
13         while((temp= input.read(data))!=-1) {
14             //這裏面需要由用戶自己來處理換行的問題,因為換行不屬於文件結束,所有內容不是-1
15             bos.write(data,0,temp);
16             if(temp<data.length) {
17                 break;
18             }
19         }
20         System.out.println("【ECHO】輸入內容:"+new String(bos.toByteArray()));
21         bos.close();
22         input.close();
23     }
24 }

  雖然實現了鍵盤輸入數據的功能,不過整體邏輯混亂,也就是說java本身所提供的System.in該操作不好用

 1 package cn.Tony.demo;
 2 import java.io.InputStream;
 3 public class TestDemo{
 4     public static void main(String[] args) throws Exception {
 5         InputStream input=System.in;//為父類實例化
 6         StringBuffer buf=new StringBuffer();
 7         System.out.println("請輸入信息:");
 8         int temp=0; 
 9         while((temp= input.read())!=-1) {
10             if(temp==‘\n‘) {
11                 break;
12             }
13             buf.append((char)temp);
14         }
15         System.out.println("【ECHO】輸入內容:"+buf);
16         input.close();
17     }
18 }

  通過以上的比較可以感受到System.in的支持度原本不高,對於英文的操作該勉強可以使用,所以要中文,就必須結合內存流來完成,所以復雜度 是很高的,如果開發都這麽寫,就非常麻煩了

總結:

  如果要想在IO中進行中文的處理,那麽最好的做法是將所有輸入的數據保存在一起再處理,這樣才可以保證出現亂發,

  BufferedReader類屬於一個緩沖的輸入流,字符流的操作對象,但是必須清楚一點,對於緩沖流在java.io中定義有兩類:字節緩沖流(BufferedInputStream),字符緩沖流(BufferedReader)。

  之所以選擇BufferedReader類操作是因為在此類中提供的readLine()方法,這個方法可以直接讀取一行數據(以回車為換行符)

    讀取一行:public String readLine()throws IOException

  但是如果要想去使用BufferedReader類有一個問題需要註意了,來觀察一下BufferdReader

技術分享圖片

範例;利用BufferedReader實現鍵盤輸入

 1 package cn.Tony.demo;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.InputStreamReader;
 5 
 6 public class TestDemo{
 7     public static void main(String[] args) throws Exception {
 8         BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));
 9         System.out.println("請輸入信息:");
10         //默認的換行模式是BufferedReader最大缺點,如果不是因為此缺點,該類還好繼續使用
11         String str=buf.readLine();//接受輸入信息,默認用回車換行
12         System.out.println(str);
13     }
14 } 

  使用以上的形式實現的鍵盤輸入還有一個最大的特點 ,由於接受的數據類型為String,那麽也就證明可以使用正則判斷。利用String類的各種操作進行處理,還可以變為各種常用的數據類型,

 1 package cn.Tony.demo;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.InputStreamReader;
 5 
 6 public class TestDemo{
 7     public static void main(String[] args) throws Exception {
 8         BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));
 9         System.out.println("請輸入信息:");
10         //默認的換行模式是BufferedReader最大缺點,如果不是因為此缺點,該類還好繼續使用
11         String str=buf.readLine();//接受輸入信息,默認用回車換行
12         if(str.matches("\\d{1,3}")) {
13             System.out.println("【ECHO】輸入信息為:"+Integer.parseInt(str));
14         }else {
15             System.out.println("輸入的數據有錯誤");
16         }
17     }
18 } 

  在很多的開發中依然可能會發現有BufferedReader類的身影,但是這個類隨著時間的偏移,基本上使用的頻率已經很低了。已經被新的類Scanner所取代了,

總結

  BufferedReader類讀取數據很方便(readLin)。

Scanner

  打印流解決的是OutputStream缺陷,BufferedRead解決的是InputStream的缺陷,而java.Util.Scanner解決的是BufferedReader類的一個缺陷。

  Scanner是一個專門進行輸入流處理的程序類,利用這個類可以方便處理數據類型。同時也可以直接結合正則表達式進行各項處理。在這個類中關註一下:

    判斷是否有指定類型的數據:public boolean hasNextXxx()

    取得指定類型的數據:public 數據 nextXxx()

    定義分隔符:public Scanner useDelimiter(Pattern pattern)

    構造方法:public Scanner(InputStream source)

範例:使用Scanner實現數據的輸入

 1 package cn.Tony.demo;
 2 
 3 import java.util.Scanner;
 4 
 5 public class TestDemo{
 6     public static void main(String[] args) throws Exception {
 7         Scanner scan=new Scanner(System.in);
 8         System.out.println("請輸入數據:");
 9         if(scan.hasNext()) {//現在有輸入內容,不判斷空字符串
10             System.out.println("【ECHO】輸入內容為:"+scan.next());
11         }
12         scan.close();
13     }
14 }

  使用Scanner輸入還可以接收各種數據類型

範例:

 1 package cn.Tony.demo;
 2 
 3 import java.util.Scanner;
 4 
 5 public class TestDemo{
 6     public static void main(String[] args) throws Exception {
 7         Scanner scan=new Scanner(System.in);
 8         System.out.println("請輸入數據:");
 9         if(scan.hasNextInt()) {//現在有輸入內容,不判斷空字符串
10             int age=scan.nextInt();
11             System.out.println("【ECHO】輸入內容為:"+age);
12         }else{
13             System.out.println("ERROR:輸入不是數字");
14         }
15         scan.close();
16     }
17 } 

  最為重要的文圖它可以對接收的數據類型使用正則表達式進行判斷。

範例:利用正則進行判斷

 1 package cn.Tony.demo;
 2 
 3 import java.util.Scanner;
 4 
 5 public class TestDemo{
 6     public static void main(String[] args) throws Exception {
 7         Scanner scan=new Scanner(System.in);
 8         System.out.println("請輸入數據:");
 9         if(scan.hasNext("\\d{4}-\\d{2}-\\d{2}")) {
10             String birthday=scan.next();
11             System.out.println("生日:"+birthday);
12         }else {
13             System.out.println("錯誤");
14         }
15         scan.close();
16     }
17 } 

  但是以上的操作在開發中不會出現,

  使用Scanner本身能接收的是一個InputStream類的對象,例如:文件輸入流。

 1 package cn.Tony.demo;
 2 import java.io.File;
 3 import java.io.FileInputStream;
 4 import java.util.Scanner;
 5 public class TestDemo{
 6     public static void main(String[] args) throws Exception {
 7         Scanner scan=new Scanner(new FileInputStream(new File("D:"+File.separator+"IO"+File.separator+"data.txt")));
 8         scan.useDelimiter(":");
 9         while(scan.hasNext()) {
10             System.out.println(scan.next());
11         }
12         scan.close();
13     }
14 } 

  Scanner實際上完美的替代了BufferedReader,更好的實現了InputStream操作。

總結:

  以後除了二進制的文件拷貝處理之外,那麽只要是針對於程序的信息輸出都是用打印流。信息輸入都使用Scanner

System類對IO的支持