20.01_IO流(IO流概述及其分類)
- 1.概念
- IO流用來(lái)處理設(shè)備之間的數(shù)據(jù)傳輸
- Java對(duì)數(shù)據(jù)的操作是通過(guò)流的方式
- Java用于操作流的類都在IO包中
- 流按流向分為兩種:輸入流,輸出流。
- 流按操作類型分為兩種:
- 字節(jié)流 : 字節(jié)流可以操作任何數(shù)據(jù),因?yàn)樵谟?jì)算機(jī)中任何數(shù)據(jù)都是以字節(jié)的形式存儲(chǔ)的
- 字符流 : 字符流只能操作純字符數(shù)據(jù)疯搅,比較方便维哈。
- 2.IO流常用父類
- 字節(jié)流的抽象父類:
- InputStream
- OutputStream
- 字符流的抽象父類:
- Reader
- Writer
- 字節(jié)流的抽象父類:
- 3.IO程序書寫
- 使用前例驹,導(dǎo)入IO包中的類
- 使用時(shí)涂邀,進(jìn)行IO異常處理
- 使用后肩豁,釋放資源
20.02_IO流(FileInputStream)
- read()一次讀取一個(gè)字節(jié)
FileInputStream fis = new FileInputStream("aaa.txt"); //創(chuàng)建一個(gè)文件輸入流對(duì)象,并關(guān)聯(lián)aaa.txt int b; //定義變量,記錄每次讀到的字節(jié) while((b = fis.read()) != -1) { //將每次讀到的字節(jié)賦值給b并判斷是否是-1 System.out.println(b); //打印每一個(gè)字節(jié) } fis.close(); //關(guān)閉流釋放資源
20.03_IO流(FileInputStream返回值為什么是int)
- read()方法讀取的是一個(gè)字節(jié),為什么返回是int,而不是byte
因?yàn)樽止?jié)輸入流可以操作任意類型的文件,比如圖片音頻等,這些文件底層都是以二進(jìn)制形式的存儲(chǔ)的,如果每次讀取都返回byte,有可能在讀到中間的時(shí)候遇到111111111 那么這11111111是byte類型的-1,我們的程序是遇到-1就會(huì)停止不讀了,后面的數(shù)據(jù)就讀不到了,所以在讀取的時(shí)候用int類型接收,如果11111111會(huì)在其前面補(bǔ)上 24個(gè)0湊足4個(gè)字節(jié),那么byte類型的-1就變成int類型的255了這樣可以保證整個(gè)數(shù)據(jù)讀完,而結(jié)束標(biāo)記的-1就是int類型
20.04_IO流(FileOutputStream)
- write()一次寫出一個(gè)字節(jié)
FileOutputStream fos = new FileOutputStream("bbb.txt"); //如果沒有bbb.txt,會(huì)創(chuàng)建出一個(gè) //fos.write(97); //雖然寫出的是一個(gè)int數(shù),但是在寫出的時(shí)候會(huì)將前面的24個(gè)0去掉,所以寫出的一個(gè)byte fos.write(98); fos.write(99); fos.close();
20.05_IO流(FileOutputStream追加)
- A:案例演示
- FileOutputStream的構(gòu)造方法寫出數(shù)據(jù)如何實(shí)現(xiàn)數(shù)據(jù)的追加寫入
FileOutputStream fos = new FileOutputStream("bbb.txt",true); //如果沒有bbb.txt,會(huì)創(chuàng)建出一個(gè) //fos.write(97); //雖然寫出的是一個(gè)int數(shù),但是在寫出的時(shí)候會(huì)將前面的24個(gè)0去掉,所以寫出的一個(gè)byte fos.write(98); fos.write(99); fos.close();
20.06_IO流(拷貝圖片)
FileInputStream讀取
-
FileOutputStream寫出
FileInputStream fis = new FileInputStream("致青春.mp3"); //創(chuàng)建輸入流對(duì)象,關(guān)聯(lián)a.jpg FileOutputStream fos = new FileOutputStream("copy.mp3");//創(chuàng)建輸出流對(duì)象,關(guān)聯(lián)b.jpg int b; while((b = fis.read()) != -1) { fos.write(b); } fis.close(); fos.close();
20.07_IO流(拷貝音頻文件畫原理圖)
- A:案例演示
- 字節(jié)流一次讀寫一個(gè)字節(jié)復(fù)制音頻
- 弊端:效率太低
20.08_IO流(字節(jié)數(shù)組拷貝之a(chǎn)vailable()方法)
-
A:案例演示
- int read(byte[] b):一次讀取一個(gè)字節(jié)數(shù)組
- write(byte[] b):一次寫出一個(gè)字節(jié)數(shù)組
- available()獲取讀的文件所有的字節(jié)個(gè)數(shù)
-
弊端:有可能會(huì)內(nèi)存溢出
FileInputStream fis = new FileInputStream("致青春.mp3"); FileOutputStream fos = new FileOutputStream("copy.mp3"); byte[] arr = new byte[fis.available()]; //根據(jù)文件大小做一個(gè)字節(jié)數(shù)組 fis.read(arr); //將文件上的所有字節(jié)讀取到數(shù)組中 fos.write(arr); //將數(shù)組中的所有字節(jié)一次寫到了文件上 fis.close(); fos.close();
20.09_IO流(定義小數(shù)組)
- write(byte[] b)
- write(byte[] b, int off, int len)寫出有效的字節(jié)個(gè)數(shù)
20.10_IO流(定義小數(shù)組的標(biāo)準(zhǔn)格式)
- A:案例演示
-
字節(jié)流一次讀寫一個(gè)字節(jié)數(shù)組復(fù)制圖片和視頻
FileInputStream fis = new FileInputStream("致青春.mp3");
FileOutputStream fos = new FileOutputStream("copy.mp3");
int len;
byte[] arr = new byte[1024 * 8]; //自定義字節(jié)數(shù)組while((len = fis.read(arr)) != -1) {
//fos.write(arr);
fos.write(arr, 0, len); //寫出字節(jié)數(shù)組寫出有效個(gè)字節(jié)個(gè)數(shù)
}fis.close();
fos.close();
-
20.11_IO流(BufferedInputStream和BufferOutputStream拷貝)
-
A:緩沖思想
- 字節(jié)流一次讀寫一個(gè)數(shù)組的速度明顯比一次讀寫一個(gè)字節(jié)的速度快很多替久,
- 這是加入了數(shù)組這樣的緩沖區(qū)效果凉泄,java本身在設(shè)計(jì)的時(shí)候,
- 也考慮到了這樣的設(shè)計(jì)思想(裝飾設(shè)計(jì)模式后面講解)蚯根,所以提供了字節(jié)緩沖區(qū)流
-
B.BufferedInputStream
- BufferedInputStream內(nèi)置了一個(gè)緩沖區(qū)(數(shù)組)
- 從BufferedInputStream中讀取一個(gè)字節(jié)時(shí)
- BufferedInputStream會(huì)一次性從文件中讀取8192個(gè), 存在緩沖區(qū)中, 返回給程序一個(gè)
- 程序再次讀取時(shí), 就不用找文件了, 直接從緩沖區(qū)中獲取
- 直到緩沖區(qū)中所有的都被使用過(guò), 才重新從文件中讀取8192個(gè)
-
C.BufferedOutputStream
- BufferedOutputStream也內(nèi)置了一個(gè)緩沖區(qū)(數(shù)組)
- 程序向流中寫出字節(jié)時(shí), 不會(huì)直接寫到文件, 先寫到緩沖區(qū)中
- 直到緩沖區(qū)寫滿, BufferedOutputStream才會(huì)把緩沖區(qū)中的數(shù)據(jù)一次性寫到文件里
-
D.拷貝的代碼
FileInputStream fis = new FileInputStream("致青春.mp3"); //創(chuàng)建文件輸入流對(duì)象,關(guān)聯(lián)致青春.mp3 BufferedInputStream bis = new BufferedInputStream(fis); //創(chuàng)建緩沖區(qū)對(duì)fis裝飾 FileOutputStream fos = new FileOutputStream("copy.mp3"); //創(chuàng)建輸出流對(duì)象,關(guān)聯(lián)copy.mp3 BufferedOutputStream bos = new BufferedOutputStream(fos); //創(chuàng)建緩沖區(qū)對(duì)fos裝飾 int b; while((b = bis.read()) != -1) { bos.write(b); } bis.close(); //只關(guān)裝飾后的對(duì)象即可 bos.close();
20.12_IO流(小數(shù)組的讀寫和帶Buffered的讀取哪個(gè)更快)
- 定義小數(shù)組如果是8192個(gè)字節(jié)大小和Buffered比較的話
- 定義小數(shù)組會(huì)略勝一籌,因?yàn)樽x和寫操作的是同一個(gè)數(shù)組
- 而Buffered操作的是兩個(gè)數(shù)組
20.13_IO流(flush和close方法的區(qū)別)
- flush()方法
- 用來(lái)刷新緩沖區(qū)的,刷新后可以再次寫出
- close()方法
- 用來(lái)關(guān)閉流釋放資源的的,如果是帶緩沖區(qū)的流對(duì)象的close()方法,不但會(huì)關(guān)閉流,還會(huì)再關(guān)閉流之前刷新緩沖區(qū),關(guān)閉后不能再寫出
20.14_IO流(字節(jié)流讀寫中文)
- 字節(jié)流讀取中文的問(wèn)題
- 字節(jié)流在讀中文的時(shí)候有可能會(huì)讀到半個(gè)中文,造成亂碼
- 字節(jié)流寫出中文的問(wèn)題
- 字節(jié)流直接操作的字節(jié),所以寫出中文必須將字符串轉(zhuǎn)換成字節(jié)數(shù)組
- 寫出回車換行 write("\r\n".getBytes());
20.15_IO流(流的標(biāo)準(zhǔn)處理異常代碼1.6版本及其以前)
-
try finally嵌套
FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream("aaa.txt"); fos = new FileOutputStream("bbb.txt"); int b; while((b = fis.read()) != -1) { fos.write(b); } } finally { try { if(fis != null) fis.close(); }finally { if(fos != null) fos.close(); } }
20.16_IO流(流的標(biāo)準(zhǔn)處理異常代碼1.7版本)
-
try close
try( FileInputStream fis = new FileInputStream("aaa.txt"); FileOutputStream fos = new FileOutputStream("bbb.txt"); MyClose mc = new MyClose(); ){ int b; while((b = fis.read()) != -1) { fos.write(b); } }
-
原理
- 在try()中創(chuàng)建的流對(duì)象必須實(shí)現(xiàn)了AutoCloseable這個(gè)接口,如果實(shí)現(xiàn)了,在try后面的{}(讀寫代碼)執(zhí)行后就會(huì)自動(dòng)調(diào)用,流對(duì)象的close方法將流關(guān)掉
20.17_IO流(圖片加密)
-
給圖片加密
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.jpg")); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.jpg")); int b; while((b = bis.read()) != -1) { bos.write(b ^ 123); } bis.close(); bos.close();
20.18_IO流(拷貝文件)
-
在控制臺(tái)錄入文件的路徑,將文件拷貝到當(dāng)前項(xiàng)目下
Scanner sc = new Scanner(System.in); System.out.println("請(qǐng)輸入一個(gè)文件路徑"); String line = sc.nextLine(); //將鍵盤錄入的文件路徑存儲(chǔ)在line中 File file = new File(line); //封裝成File對(duì)象 FileInputStream fis = new FileInputStream(file); FileOutputStream fos = new FileOutputStream(file.getName()); int len; byte[] arr = new byte[8192]; //定義緩沖區(qū) while((len = fis.read(arr)) != -1) { fos.write(arr,0,len); } fis.close(); fos.close();
20.19_IO流(錄入數(shù)據(jù)拷貝到文件)
-
將鍵盤錄入的數(shù)據(jù)拷貝到當(dāng)前項(xiàng)目下的text.txt文件中,鍵盤錄入數(shù)據(jù)當(dāng)遇到quit時(shí)就退出
Scanner sc = new Scanner(System.in); FileOutputStream fos = new FileOutputStream("text.txt"); System.out.println("請(qǐng)輸入:"); while(true) { String line = sc.nextLine(); if("quit".equals(line)) break; fos.write(line.getBytes()); fos.write("\r\n".getBytes()); } fos.close();