第十章 一 InputStream與OutputStreamjava
串流設計的概念 Java將輸入/輸出抽象化爲串流,數據有來源及目的地,銜接二者的是串流對象。數據就比如水,串流就像水管,經過水管的銜接,水由一端流向另外一端。從應用程序角度來看,若要將數據歷來源取出,可使用輸入串流,要將數據寫入目的地,可使用輸出串流。在Java中,輸入串流表明對象爲java.io.InputStream實例,輸出串流表明對象爲java.io.OutputStream實例。不管數據源和目的爲什麼,只要取的InputStream或者OutputStream的實例,操做輸入輸出的方法是一致的。 設計一個通用的dump()方法: import java.io.*;web
public class IO {數組
public static void dump(InputStram src,OutputStream dest) throws IOException{網絡
try (InputStram input = src;OutputStream output = dest) {架構
byte[] data = new byte[1024]; int length; while ((length = input.read(data)!= -1) { output.write(data,0,length); } } } } dump()方法接受InputStream與OutputStream的實例,分別表明讀取數據的來源,以及輸出數據的目的地。在進行InputStream與OutputStream的相關操做時若發生錯誤,會拋出java.io.IOException異常,在這裏不特別處理,而是在dump()方法上聲明throws,由調用dump()方法的客戶端處理。在不使用InputStream與OutputStream時,必須使用close()方法關閉串流,因爲InputStream與OutputStream操做了java.io.Closeable接口,其父接口爲java.lang.AutoCloseable接口,所以可以使用JDK7嘗試自動關閉資源語法。每次從InputStream讀入的數據,都會置入byte數組中,InputStream的read()方法每次會嘗試讀入byte數組長度的數據,並返回實際讀入的字節,只要不是-1,就表示讀取到數據,可使用OutputStream的write()方法,指定要寫出的byte數組、初始索引與數據長度。
書上雖然沒有正式介紹到網絡程序設計,不過java.net.URL的使用很簡單,只要指定網址,URL實例會自動進行HTTP協議,可使用openStream方法取得InputStream實例,表明與網站鏈接的數據串流。學習
串流繼承架構 System.in與System.out它們分別是InputStream與PrintStream的實例,分別表明標準輸入與標準輸出,以我的計算機而言,一般對應至文本模式中的輸入與輸出。 可使用System的setIn()方法指定InputStream實例,從新指定標準輸入來源。 System的setOut()方法指定PrintStream實例,將結果輸出至指定的目的地。 import java.io.*; public class StandarOut{ public static void main (String[] args) throws IOException { try (PrintStream printStream = new PrintStream(new FileOutputStream(args[0]))) { System.out.printf("helloWorld"); } } }
PrintStream接受InputStream實例,在這個範例中用PrintStream打包FileOutputStream,你操做PrintStream相關方法,PrintStream會代你操做FileOutputStream。除了System.in與System.out以外,還有個System.err爲PrintStream實例,稱爲標準錯誤輸入串流,它是用來當即顯示錯誤信息的。網站
FileInputStream與FileOutputStream編碼
FileInputStream是InputStream的子類,能夠指定文件名建立實例,一旦建立文檔就開啓,接着就能夠用來讀取數據,FileOutputStream是OutputStream的子類,能夠指定文件名建立實例,一旦建立文檔就開啓,接着就能夠用來寫出數據,不管FileInputStream仍是FileOutputStream,不使用時都要用close()關閉文檔。spa
ByteArrayInputStream與ByteArrayOutputStream.net
ByteArrayInputStream是InputStream的子類,可指定byte數組建立實例。一旦建立就能夠將byte數組看成數據源進行讀取。ByteArrayOutputStream是OutputStream的子類,可指定byte數組建立實例。一旦建立就能夠將byte數組看成目的地寫出數據。
串流處理裝飾器
InputStream、OutputStream提供串流基本操做,若是想要爲輸入/輸出的數據作加工處理,則可使用打包器類。前面示範過的Scanner類就是做爲打包器,其接受InputStream實例,你操做Scanner打包器相關方法,Scanner會實際操做打包的InputStream取得數據,並轉換爲你想要的數據類型。InputStream、OutputStream的一些子類也具備打包器的做用。前面介紹的PrintStream就是實際例子,你操做PrintStream的print()、println()等方法,PrintStream會自動轉換爲byte數組數據,利用打包的OutputStream進行輸出。下面介紹幾種經常使用的串流裝飾器類。第一種BufferedInputStream與BufferedOutputStream,二者都具有緩衝做用。若是InputStream第一次read()時能夠儘可能讀取足夠的數據至內存的緩衝區,後續調用read()時先看看緩衝區是否是還有數據,若是有就從緩衝區讀取,沒有再歷來源讀取數據至緩衝區,這樣減小歷來源直接讀取數據的次數,對讀取效率將會有幫助。畢竟內存的訪問速度較快。若是OutputStream每次write()時可將數據寫入內存中的緩衝區,緩衝區滿了再將緩衝區的數據寫入目的地,這樣可減小對目的地的寫入次數,對寫入效率也會有幫助。第二種是DataInputStream與DataOutputStream,DataInputStream與DataOutputStream提供讀取、寫入Java基本數據類型的方法,像是讀寫int、double、boolean等的方法。這些方法會自動在指定的類型與字節間轉換。第三種是ObjectInputStream與ObjectOutputStream,ObjectInputStream與ObjectOutputStream能夠將內存中的對象整個儲存下來,以後再讀入還原爲對象。ObjectInputStream提供readObject()方法將數據讀入爲對象,而ObjectOutputStream提供writeObject()方法將對象寫至目的地,能夠被這兩個方法處理的對象,必須操做java.io.Serializable接口,這個接口並無定義任何方法,只是做爲標示之用,表示這個對象是能夠串行化的。若是在作對象串行化時,對象中某些數據成員不但願被寫出,則能夠標上transient關鍵字。
字符處理類 Reader與Writer繼承架構 針對字符數據的讀取,Java SE提供了java.io.Reader類,其抽象化了字符數據讀入的來源,針對字符數據的寫入,則提供了java.io.Writer類,其抽象化了數據寫出的目的地。在不使用Reader與Writer時,必須使用close()方法關閉串流。Reader與Writer操做了Closeable接口,其父接口爲AutoCloseable接口,所以可以使用JDK7嘗試自動關閉資源語法。StringReader能夠將字符串打包,看成讀取來源,StringWriter則能夠做爲寫入目的地,最後用toString()取得全部寫入的字符組成的字符串。在啓動JVM時,能夠用-Dfile.encoding來指定FileReader、FileWriter所使用的編碼。
2.字符處理裝飾器
若是串流處理的字節數據,實際上表明某些字符的編碼數據,而你想要將這些字節數據轉換爲對應的編碼字符,可使用InputStreamReader、OutputStreamWriter對串流數據打包,在創建InputStreamReader與OutputStreamWriter時,能夠指定編碼,若是沒有指定編碼,則以JVM啓動時所獲取的默認編碼來作字符轉換。PrintStream與PrintWriter使用上極爲類似,不過除了能夠對OutputStream打包以外,PrintWriter還能夠對Writer進行打包,提供print()、println()、format()等方法。