Java IO之包裝流詳解
根據(jù)功能分為節(jié)點(diǎn)流和包裝流(處理流)
節(jié)點(diǎn)流:可以從或向一個(gè)特定的地方(節(jié)點(diǎn))讀寫數(shù)據(jù)。如FileReader.
處理流:是對(duì)一個(gè)已存在的流的連接和封裝,通過(guò)所封裝的流的功能調(diào)用實(shí)現(xiàn)數(shù)據(jù)讀寫。如BufferedReader.處理流的構(gòu)造方法總是要帶一個(gè)其他的流對(duì)象做參數(shù)。一個(gè)流對(duì)象經(jīng)過(guò)其他流的多次包裝,稱為流的鏈接。
1、前面講的字符輸入輸出流,字節(jié)輸入輸出流都是字節(jié)流。那么什么是包裝流呢?
①、包裝流隱藏了底層節(jié)點(diǎn)流的差異,并對(duì)外提供了更方便的輸入\輸出功能,讓我們只關(guān)心這個(gè)高級(jí)流的操作
②、使用包裝流包裝了節(jié)點(diǎn)流,程序直接操作包裝流,而底層還是節(jié)點(diǎn)流和IO設(shè)備操作
③、關(guān)閉包裝流的時(shí)候,只需要關(guān)閉包裝流即可
2、緩沖流
緩沖流:是一個(gè)包裝流,目的是緩存作用,加快讀取和寫入數(shù)據(jù)的速度。
字節(jié)緩沖流:BufferedInputStream
、BufferedOutputStream
字符緩沖流:BufferedReader
、BufferedWriter
案情回放:我們?cè)趯⒆址斎胼敵隽?、字?jié)輸入輸出流的時(shí)候,讀取操作,通常都會(huì)定義一個(gè)字節(jié)或字符數(shù)組,將讀取/寫入的數(shù)據(jù)先存放到這個(gè)數(shù)組里面,然后在取數(shù)組里面的數(shù)據(jù)。這比我們一個(gè)一個(gè)的讀取/寫入數(shù)據(jù)要快很多,而這也就是緩沖流的由來(lái)。只不過(guò)緩沖流里面定義了一個(gè) 數(shù)組用來(lái)存儲(chǔ)我們讀取/寫入的數(shù)據(jù),當(dāng)內(nèi)部定義的數(shù)組滿了(注意:我們操作的時(shí)候外部還是會(huì)定義一個(gè)小的數(shù)組,小數(shù)組放入到內(nèi)部數(shù)組中),就會(huì)進(jìn)行下一步操作。
下面是沒有用緩沖流的操作:
//1、創(chuàng)建目標(biāo)對(duì)象,輸入流表示那個(gè)文件的數(shù)據(jù)保存到程序中。不寫盤符,默認(rèn)該文件是在該項(xiàng)目的根目錄下 //a.txt 保存的文件內(nèi)容為:AAaBCDEF File target = new File("io"+File.separator+"a.txt"); //2、創(chuàng)建輸入流對(duì)象 InputStream in = new FileInputStream(target); //3、具體的 IO 操作(讀取 a.txt 文件中的數(shù)據(jù)到程序中) /** * 注意:讀取文件中的數(shù)據(jù),讀到最后沒有數(shù)據(jù)時(shí),返回-1 * int read():讀取一個(gè)字節(jié),返回讀取的字節(jié) * int read(byte[] b):讀取多個(gè)字節(jié),并保存到數(shù)組 b 中,從數(shù)組 b 的索引為 0 的位置開始存儲(chǔ),返回讀取了幾個(gè)字節(jié) * int read(byte[] b,int off,int len):讀取多個(gè)字節(jié),并存儲(chǔ)到數(shù)組 b 中,從數(shù)組b 的索引為 0 的位置開始,長(zhǎng)度為len個(gè)字節(jié) */ //int read():讀取一個(gè)字節(jié),返回讀取的字節(jié) int data1 = in.read();//獲取 a.txt 文件中的數(shù)據(jù)的第一個(gè)字節(jié) System.out.println((char)data1); //A //int read(byte[] b):讀取多個(gè)字節(jié)保存到數(shù)組b 中 byte[] buffer = new byte[10];//這里我們定義了一個(gè) 長(zhǎng)度為 10 的字節(jié)數(shù)組,用來(lái)存儲(chǔ)讀取的數(shù)據(jù) in.read(buffer);//獲取 a.txt 文件中的前10 個(gè)字節(jié),并存儲(chǔ)到 buffer 數(shù)組中 System.out.println(Arrays.toString(buffer)); //[65, 97, 66, 67, 68, 69, 70, 0, 0, 0] System.out.println(new String(buffer)); //AaBCDEF[][][] //int read(byte[] b,int off,int len):讀取多個(gè)字節(jié),并存儲(chǔ)到數(shù)組 b 中,從索引 off 開始到 len in.read(buffer, 0, 3); System.out.println(Arrays.toString(buffer)); //[65, 97, 66, 0, 0, 0, 0, 0, 0, 0] System.out.println(new String(buffer)); //AaB[][][][][][][] //4、關(guān)閉流資源 in.close();
我們查看 緩沖流的 JDK 底層源碼,可以看到,程序中定義了這樣的 緩存數(shù)組,大小為 8192
BufferedInputStream:
BufferedOutputStream:
//字節(jié)緩沖輸入流 BufferedInputStream bis = new BufferedInputStream( new FileInputStream("io"+File.separator+"a.txt")); //定義一個(gè)字節(jié)數(shù)組,用來(lái)存儲(chǔ)數(shù)據(jù) byte[] buffer = new byte[1024]; int len = -1;//定義一個(gè)整數(shù),表示讀取的字節(jié)數(shù) while((len=bis.read(buffer))!=-1){ System.out.println(new String(buffer,0,len)); } //關(guān)閉流資源 bis.close();<br data-filtered="filtered"><br data-filtered="filtered"> //字節(jié)緩沖輸出流 BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream("io"+File.separator+"a.txt")); bos.write("ABCD".getBytes()); bos.close();
//字符緩沖輸入流 BufferedReader br = new BufferedReader( new FileReader("io"+File.separator+"a.txt")); char[] buffer = new char[10]; int len = -1; while((len=br.read(buffer))!=-1){ System.out.println(new String(buffer,0,len)); } br.close(); //字符緩沖輸出流 BufferedWriter bw = new BufferedWriter( new FileWriter("io"+File.separator+"a.txt")); bw.write("ABCD"); bw.close();
3、轉(zhuǎn)換流:把字節(jié)流轉(zhuǎn)換為字符流
InputStreamReader
:把字節(jié)輸入流轉(zhuǎn)換為字符輸入流
OutputStreamWriter
:把字節(jié)輸出流轉(zhuǎn)換為字符輸出流
用轉(zhuǎn)換流進(jìn)行文件的復(fù)制:
/** * 將 a.txt 文件 復(fù)制到 b.txt 中 */ //1、創(chuàng)建源和目標(biāo) File srcFile = new File("io"+File.separator+"a.txt"); File descFile = new File("io"+File.separator+"b.txt"); //2、創(chuàng)建字節(jié)輸入輸出流對(duì)象 InputStream in = new FileInputStream(srcFile); OutputStream out = new FileOutputStream(descFile); //3、創(chuàng)建轉(zhuǎn)換輸入輸出對(duì)象 Reader rd = new InputStreamReader(in); Writer wt = new OutputStreamWriter(out); //3、讀取和寫入操作 char[] buffer = new char[10];//創(chuàng)建一個(gè)容量為 10 的字符數(shù)組,存儲(chǔ)已經(jīng)讀取的數(shù)據(jù) int len = -1;//表示已經(jīng)讀取了多少個(gè)字符,如果是 -1,表示已經(jīng)讀取到文件的末尾 while((len=rd.read(buffer))!=-1){ wt.write(buffer, 0, len); } //4、關(guān)閉流資源 rd.close(); wt.close();
4、內(nèi)存流(數(shù)組流):
把數(shù)據(jù)先臨時(shí)存在數(shù)組中,也就是內(nèi)存中。所以關(guān)閉 內(nèi)存流是無(wú)效的,關(guān)閉后還是可以調(diào)用這個(gè)類的方法。底層源碼的 close()是一個(gè)空方法
①、字節(jié)內(nèi)存流:ByteArrayOutputStream
、ByteArrayInputStream
//字節(jié)數(shù)組輸出流:程序---》內(nèi)存 ByteArrayOutputStream bos = new ByteArrayOutputStream(); //將數(shù)據(jù)寫入到內(nèi)存中 bos.write("ABCD".getBytes()); //創(chuàng)建一個(gè)新分配的字節(jié)數(shù)組。 其大小是此輸出流的當(dāng)前大小,緩沖區(qū)的有效內(nèi)容已被復(fù)制到其中。 byte[] temp = bos.toByteArray(); System.out.println(new String(temp,0,temp.length)); byte[] buffer = new byte[10]; ///字節(jié)數(shù)組輸入流:內(nèi)存---》程序 ByteArrayInputStream bis = new ByteArrayInputStream(temp); int len = -1; while((len=bis.read(buffer))!=-1){ System.out.println(new String(buffer,0,len)); } //這里不寫也沒事,因?yàn)樵创a中的 close()是一個(gè)空的方法體 bos.close(); bis.close();
②、字符內(nèi)存流:CharArrayReader
、CharArrayWriter
//字符數(shù)組輸出流 CharArrayWriter caw = new CharArrayWriter(); caw.write("ABCD"); //返回內(nèi)存數(shù)據(jù)的副本 char[] temp = caw.toCharArray(); System.out.println(new String(temp)); //字符數(shù)組輸入流 CharArrayReader car = new CharArrayReader(temp); char[] buffer = new char[10]; int len = -1; while((len=car.read(buffer))!=-1){ System.out.println(new String(buffer,0,len)); }
③、字符串流:StringReader
,StringWriter
(把數(shù)據(jù)臨時(shí)存儲(chǔ)到字符串中)
//字符串輸出流,底層采用 StringBuffer 進(jìn)行拼接 StringWriter sw = new StringWriter(); sw.write("ABCD"); sw.write("帥鍋"); System.out.println(sw.toString());//ABCD帥鍋 //字符串輸入流 StringReader sr = new StringReader(sw.toString()); char[] buffer = new char[10]; int len = -1; while((len=sr.read(buffer))!=-1){ System.out.println(new String(buffer,0,len));//ABCD帥鍋 }
5、合并流:把多個(gè)輸入流合并為一個(gè)流,也叫順序流,因?yàn)樵谧x取的時(shí)候是先讀第一個(gè),讀完了在讀下面一個(gè)流。
//定義字節(jié)輸入合并流 SequenceInputStream seinput = new SequenceInputStream( new FileInputStream("io/a.txt"), new FileInputStream("io/b.txt")); byte[] buffer = new byte[10]; int len = -1; while((len=seinput.read(buffer))!=-1){ System.out.println(new String(buffer,0,len)); } seinput.close();
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
詳解用JWT對(duì)SpringCloud進(jìn)行認(rèn)證和鑒權(quán)
這篇文章主要介紹了詳解用JWT對(duì)SpringCloud進(jìn)行認(rèn)證和鑒權(quán),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03idea使用Maven Helper插件去掉無(wú)用的poom 依賴信息(詳細(xì)步驟)
這篇文章主要介紹了idea使用Maven Helper插件去掉無(wú)用的poom 依賴信息,本文分步驟給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04spring入門教程之bean的繼承與自動(dòng)裝配詳解
眾所周知Spring里面的bean就類似是定義的一個(gè)組件,而這個(gè)組件的作用就是實(shí)現(xiàn)某個(gè)功能的,下面這篇文章主要給大家介紹了關(guān)于spring入門教程之bean繼承與自動(dòng)裝配的相關(guān)資料,需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11javaweb servlet中使用請(qǐng)求轉(zhuǎn)發(fā)亂碼的實(shí)現(xiàn)
下面小編就為大家?guī)?lái)一篇javaweb servlet中使用請(qǐng)求轉(zhuǎn)發(fā)亂碼的實(shí)現(xiàn)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-08-08MyBatis?Generator快速生成實(shí)體類和映射文件的方法
這篇文章主要介紹了MyBatis?Generator快速生成實(shí)體類和映射文件的方法,通過(guò)示例代碼介紹了MyBatis?Generator?的使用,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10Java實(shí)現(xiàn)簡(jiǎn)單碰撞檢測(cè)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單碰撞檢測(cè),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06java多線程抓取鈴聲多多官網(wǎng)的鈴聲數(shù)據(jù)
很容易就能發(fā)現(xiàn)通過(guò)改變 listId和page就能從服務(wù)器獲取鈴聲的json數(shù)據(jù), 通過(guò)解析json數(shù)據(jù), 可以看到都帶有{"hasmore":1,"curpage":1}這樣子的指示,通過(guò)判斷hasmore的值,決定是否進(jìn)行下一頁(yè)的抓取。 但是通過(guò)上面這個(gè)鏈接返回的json中不帶有鈴聲的下載地址2016-04-04