System類對IO的支持
系統輸出
學完了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 5public 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的支持