對于任何程序設計語言而言,輸入輸出(Input/Output)系統(tǒng)都是非常核心的功能。程序運行需要數(shù)據(jù)绞吁,數(shù)據(jù)的獲取往往需要跟外部系統(tǒng)進行通信厘唾,外部系統(tǒng)可能是文件、數(shù)據(jù)庫鹃操、其他程序韭寸、網(wǎng)絡、IO設備等等组民。外部系統(tǒng)比較復雜多變棒仍,那么我們有必要通過某種手段進行抽象、屏蔽外部的差異臭胜,從而實現(xiàn)更加便捷的編程莫其。
i:輸入(Input)指的是:可以讓程序從外部系統(tǒng)獲得數(shù)據(jù)(核心含義是“讀”癞尚,讀取外部數(shù)據(jù))。
o:輸出(Output)指的是:程序輸出數(shù)據(jù)給外部系統(tǒng)從而可以操作外部系統(tǒng)(核心含義是“寫”乱陡,將數(shù)據(jù)寫出到外部系統(tǒng))浇揩。
流:流是一個抽象、動態(tài)的概念憨颠,是一連串連續(xù)動態(tài)的數(shù)據(jù)集合胳徽。
對于輸入(Input)流而言,數(shù)據(jù)源就像水箱爽彤,流(stream)就像水管中流動著的水流养盗,程序就是我們最終的用戶。我們通過流(A Stream)將數(shù)據(jù)源(Source)中的數(shù)據(jù)(information)輸送到程序(Program)中适篙。
對于輸出(Output)流而言往核,目標數(shù)據(jù)源就是目的地(dest),我們通過流(A Stream)將程序(Program)中的數(shù)據(jù)(information)輸送到目的數(shù)據(jù)源(dest)中嚷节。
常見的IO流構成結構繼承關系
IO流中四大抽象類
1聂儒、InputStream
? ? ??此抽象類是表示字節(jié)輸入流的所有類的父類。InputSteam是一個抽象類硫痰,它不可以實例化衩婚。 數(shù)據(jù)的讀取需要由它的子類來實現(xiàn)。根據(jù)節(jié)點的不同效斑,它派生了不同的節(jié)點流子類 非春。
? ? ??繼承自InputSteam的流都是用于向程序中輸入數(shù)據(jù),且數(shù)據(jù)的單位為字節(jié)(8 bit)鳍悠。
? ? ??常用方法:
? ? ??int read():讀取一個字節(jié)的數(shù)據(jù)税娜,并將字節(jié)的值作為int類型返回(0-255之間的一個值)。如果未讀出字節(jié)則返回-1(返回值為-1表示讀取結束)藏研。
? ? ??void close():關閉輸入流對象敬矩,釋放相關系統(tǒng)資源。
2蠢挡、OutputStream
? ? ??此抽象類是表示字節(jié)輸出流的所有類的父類弧岳。輸出流接收輸出字節(jié)并將這些字節(jié)發(fā)送到某個目的地。
? ? ??常用方法:
? ? ??void write(int n):向目的地中寫入一個字節(jié)业踏。
? ? ??void close():關閉輸出流對象禽炬,釋放相關系統(tǒng)資源。
3勤家、 Reader
? ? ??Reader用于讀取的字符流抽象類腹尖,數(shù)據(jù)單位為字符。
? ? ??int read(): 讀取一個字符的數(shù)據(jù)伐脖,并將字符的值作為int類型返回(0-65535之間的一個值热幔,即Unicode值)乐设。如果未讀出字符則返回-1(返回值為-1表示讀取結束)。
? ? ??void close() : 關閉流對象绎巨,釋放相關系統(tǒng)資源近尚。
4、Writer
? ? ??Writer用于寫入的字符流抽象類场勤,數(shù)據(jù)單位為字符戈锻。
? ? ??void write(int n): 向輸出流中寫入一個字符。
? ? ??void close() : 關閉輸出流對象和媳,釋放相關系統(tǒng)資源格遭。
IO流中常用類:
FileInputStream:主要用于讀取文件內容,每次讀取單位是字節(jié)窗价,
代碼演示
運行結果
可以看到如庭,前面字母讀取正常,后邊出現(xiàn)了亂碼撼港,因為后邊是中文文字。每個中文文字占用1個字符=2個字節(jié)骤竹。而我們打印輸出的是一個字節(jié)帝牡,所以導致了這種情況。
FileReader:主要用于讀取文件內容蒙揣,每次讀取1個字符(2個字節(jié))靶溜,多用于文本的讀取
代碼演示
運行效果
可以看到,使用FileReader懒震,此時字母被讀出來了罩息,漢字也被正常的讀出來了。
FileOutputStream:主要用于文件內容的寫入个扰,寫入單位是字節(jié)
代碼演示
查看文件寫入是否正常瓷炮;
查看發(fā)現(xiàn),字母正常寫入递宅,而漢字顯示不正常娘香,這個原因跟上面FileInputStream原因一樣。主要是因為漢字占用一個字符(2字節(jié))办龄,而我們使用FileOutputStream每次寫入是1字節(jié)
FileWriter:主要用于文件內容的寫入烘绽,寫入單位是字符,多用于文本文件的寫入
代碼演示
查看文件寫入是否正常俐填;
可以看到安接,使用FileWriter,漢字也被正常輸出
BufferedInputStream英融、BufferedOutputStream盏檐、BufferedReader呀打、BufferedWriter這四個類都是緩存流
緩存流本身并不具有IO流的讀取與寫入功能,只是在別的流(節(jié)點流或其他處理流)上加上緩沖功能提高效率糯笙,就像是把別的流包裝起來一樣贬丛,因此緩沖流是一種處理流(包裝流)。? 當對文件或者其他數(shù)據(jù)源進行頻繁的讀寫操作時给涕,效率比較低豺憔,這時如果使用緩沖流就能夠更高效的讀寫信息。因為緩沖流是先將數(shù)據(jù)緩存起來够庙,然后當緩存區(qū)存滿后或者手動刷新時再一次性的讀取到程序或寫入目的地恭应。
演示BufferedInputStream、BufferedOutputStream和普通不帶緩存的對比
通過兩個代碼耘眨,可以看到昼榛,帶緩存的流,比普通流處理速度快太多了
DataInputStream和DataOutputStream是處理流提供了可以存取與機器無關的所有Java基礎類型數(shù)據(jù)(如:int剔难、double胆屿、String等)的方法。
代碼演示:
通過代碼演示偶宫,可以看到非迹,存在文件中的數(shù)據(jù),我們通過普通方法無法直接讀取的纯趋,但我們程序讀取是正常的憎兽;
PrintStream打印輸出流;打印指定的內容吵冒,輸出到指定位置纯命,可以是控制臺,也可以是文件等等痹栖;
代碼演示
InputStreamReader/OutputStreamWriter用來實現(xiàn)將字節(jié)流轉化成字符流
System.in是字節(jié)流對象亿汞,代表鍵盤的輸入,如果我們想按行接收用戶的輸入時结耀,就必須用到緩沖字符流BufferedReader特有的方法readLine()留夜,
但是經過觀察會發(fā)現(xiàn)在創(chuàng)建BufferedReader的構造方法的參數(shù)必須是一個Reader對象,這時候我們的轉換流InputStreamReader就派上用場了图甜。? ? ??
而System.out也是字節(jié)流對象碍粥,代表輸出到顯示器,按行讀取用戶的輸入后黑毅,并且要將讀取的一行字符串直接顯示到控制臺嚼摩,就需要用到字符流的write(String str)方法,所以我們要使用OutputStreamWriter將字節(jié)流轉化為字符流。