Java基礎——iO(二),java基礎io
接著上一篇,繼續做學習筆記。學IO這塊,突然找到一點好處,好像以後操作電腦,尤其是電腦裡的檔案啥的,可以很少的用滑鼠了。添加、修改、刪除啥的,幾行代碼就可以搞定了。這隻是我一個初學者的一點小心思,IO背後的大用處,相信還有很多很多。繼續學習ing....
一、緩衝流和裝飾模式
緩衝流(封裝類),緩衝區的出現提高了對資料讀寫的效率,它可以用來對流進行封裝,在流的基礎上對流的功能進行了增強。和底層系統提供的緩衝區有什麼區別?底層直接和目標裝置交換資料,封裝類中,通過被封裝的對象。
BufferedReader : 從字元輸入資料流中讀取文本,緩衝各個字元,從而實現字元、數組和行的高效讀取。
BufferedReader 的建構函式有兩個:
---- BufferedReader(Reader in)
---- BufferedReader(Reader in, int sz) 建立一個使用預設大小輸入緩衝區的緩衝字元輸入資料流。
//例子 BufferedWriter 的使用FileWriter w=new FileWriter("2.txt");BufferedWriter bw=new BufferedWriter(w); bw.write("這是一行內容"); bw.newLine(); //這是封裝類提供的功能 bw.write("這又是一行內容"); bw.flush(); //用緩衝流,不要忘了flush() bw.close(); //它就相當於關閉 w,這麼寫了以後,就不用再寫 w.close() 了
//例子 BufferedReader 的使用public static void main(String[] args)throws IOException { List<String> nameList= demo2(); for(String s:nameList) { System.out.println(s); }} static List<String> demo2() throws IOException { List<String> nameList=new ArrayList<String>(); FileReader r=new FileReader("C:/名單.txt"); BufferedReader br=new BufferedReader(r); String str=null; while( (str=br.readLine())!=null ){ nameList.add(str); } br.close(); return nameList;}
二、裝飾設計模式
Decorator模式(別名Wrapper):動態將職責附加到對象上,若要擴充功能,裝飾者提供了比繼承更具彈性的代替方案。當要對已有的對象進行功能增強時,可以定義類,將已有對象傳入,基於已有對象的功能,並提供加強功能。那麼自訂的該類就稱為裝飾類。裝飾類通常會通過構造方法接收被裝飾的對象,並基於被裝飾的對象的功能,提供更強的功能。
public class Teste3 { public static void main(String[] args) { Japan japan=new Japan(); NiceJapan niceJapan=new NiceJapan(japan); niceJapan.speak(); }}class Japan{ void speak(){ System.out.println("我們都是好學生"); }}class NiceJapan{ NiceJapan(Japan japan){ this.japan=japan; } private Japan japan; //組合 void speak(){ System.out.println("清清嗓子");//其他動作 System.out.println("晃晃腦袋"); japan.speak(); System.out.println("磕幾個頭"); System.out.println("發幾聲慘叫"); }}
三、位元組流概述
在不考慮負數的情況下,每個位元組中的資料,都是0-255之間的值(因為一個位元組為8位,最大為255)
如果一個檔案中的每個位元組或每相鄰的幾個位元組的資料都可以表示成某個字元,則可以將這個檔案稱為文字檔,其實這是二進位的一個特例。
(你可以開啟一個記事本,然後把一張圖片拉進去,會發現一大堆的亂碼,它就是二進位的特例,圖片上的資訊有的能與碼錶對上就被顯示出來,有的不能就亂了。這是因為,位元組流操作的時候,操作單位都是以位元組為單位進行的操作的對象不一定有碼錶對應。
概述:
1.所有位元組輸入資料流類都是抽象類別InputStream的子類
int read() 從源中讀取一個位元組的資料,返回位元組值
int read(byte b[])從源中試圖讀取b.length個位元組到b中,返回實際讀取的位元組目
void close()關閉輸入資料流
2.所有位元組輸出資料流類都是抽象類別OutputStream的子類
void write(int n) 向輸出資料流寫入單個位元組。
void write(byte b[])向輸出資料流寫入一個位元組數組
void flush()把緩衝區中內容輸出並清空緩衝區(重新整理)
void close()關閉輸出資料流
3.例子,使用位元組流進行檔案的讀寫
FileOutputStream 用於寫入諸像資料之類的原始位元組的流。要寫入字元流,請考慮使用 FileWriter。
FileOutputStream 的write方法的幾種重載形式如下:
//void write(byte[] b) //注意傳回型別是void
//void write(byte[] b, int off, int len)
//void write(int b) 將指定位元組寫入此檔案輸出資料流。
//FileInputStream 的read方法的幾種重載形式如下
//int read() 從此輸入資料流中讀取一個資料位元組。 返回讀到的位元組,到尾返回-1
//int read(byte[] b) 從此輸入資料流中將最多 b.length 個位元組的資料讀入一個 byte 數組中 返回讀的位元組數,到尾返回-1
//int read(byte[] b, int off, int len) 從此輸入資料流中將最多 len 個位元組的資料讀入一個 byte 數組中。
//對於位元組流來說,每次讀到的就是一個位元組,如果是英文,正好一個英文對應一個位元組,如果中文,就可能對應兩個位元組
static void demo1() throws IOException{ OutputStream out=new FileOutputStream("c:/file1.txt"); out.write("abcEnlish中國".getBytes()); //位元組流不重新整理也能寫出去 out.close(); InputStream in=new FileInputStream("c:/file1.txt"); int ch=0; while((ch=in.read())!=-1 ){ System.out.println((char)ch); //可以發現,如果是英文,能顯示出來,但中文會亂碼 } in.close(); }
//例子,用位元組數組進行接收static void demo1()throws IOException { InputStream in=new FileInputStream("c:/名單.txt"); byte [] buff=new byte[3]; //1024 int len=0; while( (len=in.read(buff)) !=-1 ){ String str=new String(buff,0,len); System.out.println(str); //有亂碼 }}
//例子 available 的利用static void demo2()throws IOException{ InputStream in=new FileInputStream("c:/名單.txt"); byte [] buff=new byte[in.available()]; //in.available();當前流中還有多少個位元組可讀 in.read(buff); System.out.println(new String(buff)); in.close();}
//例子.圖片的複製static void demo3()throws IOException { InputStream in=new FileInputStream("C:\\image\\lengtu.jpg"); byte [] buff=new byte[in.available()]; in.read(buff); OutputStream out=new FileOutputStream("E:/tuzi.jpg"); out.write(buff); in.close(); out.close();}
補充:
前面,字元流有封裝類
BufferedReader, BufferedWriter
位元組流也有封裝類
BufferedInputStream, BufferedOutputStream
四、轉換流 InputStreamReader , OutputStreamWriter
把位元組輸入資料流轉為字元輸入資料流:
InputStreamReader
public class InputStreamReader extends Reader
把位元組輸出資料流轉為字元輸出資料流:
OutputStreamWriter
public class OutputStreamWriter extends Writer
1) InputStreamReader
它有四個建構函式:
InputStreamReader(InputStream in)
InputStreamReader(InputStream in, Charset cs)
InputStreamReader(InputStream in, CharsetDecoder dec) //CharsetDecoder 解碼器
InputStreamReader(InputStream in, String charsetName)
2) OutputStreamWriter
它有四個建構函式:
OutputStreamWriter(OutputStream out) //建立使用預設字元編碼的 OutputStreamWriter。
OutputStreamWriter(OutputStream out, CharsetEncoder enc) // 建立使用給定字元集的 OutputStreamWriter。
OutputStreamWriter(OutputStream out, String charsetName) // 建立使用給定字元集編碼器的 OutputStreamWriter。
OutputStreamWriter(OutputStream out, String charsetName) // 建立使用指定字元集的 OutputStreamWriter。
//例子,用緩衝流封裝轉換流,轉換流轉換位元組流InputStream in=new FileInputStream("c:/1.txt"); InputStreamReader inputReader=new InputStreamReader(in); BufferedReader br=new BufferedReader(inputReader); String str=null; while((str=br.readLine())!=null){ System.out.println(str);}
//例子 從鍵盤讀入資料,轉成大寫列印出來public static void main(String[] args) throws IOException { BufferedReader br=new BufferedReader( new InputStreamReader(System.in)); String msg=null; while((msg=br.readLine())!=null){ System.out.println(msg.toUpperCase()); }}
五、 ByteArrayInputStream 與ByteArrayOutputStream
它是用來以IO流的方式,完成對位元組數組內容的讀寫,支援類似記憶體虛擬檔案或記憶體映象檔案的功能。
關閉 ByteArrayOutputStream 無效。此類中的方法在關閉此流後仍可被調用,而不會產生任何IOException。
//ByteArrayInputStream(byte[] buff)
//ByteArrayInputStream(byte[] buff,int offset,int length)
//ByteArrayOutStream () //沒有傳參,則預設建立一個32位元組的緩衝區,其中的資料被寫入一個 byte 數組。緩衝區會隨著資料的不斷寫入而自動成長。可使用 toByteArray()和toString()擷取資料。
//ByteArrayOutStream(int size) 根據指定大小建立緩衝區
//ByteArrayOutStream 的 byte[] toByteArray() 建立一個新分配的 byte 數組。其大小是此輸出資料流的當前大小,並且緩衝區的有效內容已複製到該數組中
//例子,使用 ByteArrayOutputStream ByteArrayOutputStream byteOut=new ByteArrayOutputStream(); byteOut.write("這是放在虛擬記憶體中的資料".getBytes()); byte[] byteArray=byteOut.toByteArray(); String str=new String(byteArray); System.out.println(str);
//加強 從輸入資料流中,讀取字元,然後把字元變成大寫,寫入到輸出資料流中public static void main(String[] args) throws IOException { /* 樣本1 用 ByteArrayInputStream 和 ByteArrayOutputStream ByteArrayInputStream in=new ByteArrayInputStream("abcdef".getBytes()); ByteArrayOutputStream out=new ByteArrayOutputStream(); transform(in,out); byte [] contents=out.toByteArray(); String str=new String(contents); System.out.println(str); */ // 樣本2 用鍵盤輸入輸出資料流 transform(System.in,System.out); // 樣本3 用檔案輸入輸出資料流 InputStream in =new FileInputStream("c:/1.txt"); OutputStream out =new FileOutputStream("e:/big.txt"); transform(in,out); } static void transform(InputStream in,OutputStream out) throws IOException{ int ch=0; while((ch=in.read())!=-1){ out.write(Character.toUpperCase(ch)); }}