一,IO流的分類
A,按照操作的對(duì)象不同可分為字節(jié)流與字符流
B,按照流的方向不同可分為輸入(指從外部存儲(chǔ)設(shè)備拿文件到內(nèi)存)流也叫讀與輸出(指從內(nèi)存把文件寫入到外部存儲(chǔ)設(shè)備)流也叫寫
注:字節(jié)流可以操作任何類型的文件,字符流是后來才出現(xiàn)的,主要用來操作字符類的文件;字符流的出現(xiàn)源于編碼表的問題,一開始計(jì)算機(jī)內(nèi)使用ANSII編碼,后來每種語(yǔ)言都有了自己的編碼方式即編碼表,為了統(tǒng)一這些編碼信息國(guó)際標(biāo)準(zhǔn)化組織便產(chǎn)生了Unicode編碼信息表來把世界各國(guó)的語(yǔ)言都包括在內(nèi),此編碼表采用兩個(gè)字節(jié)即16位來存儲(chǔ)每一個(gè)字符,java內(nèi)置的編碼表便是Unicode編碼;字符流是當(dāng)讀取文件的時(shí)候,以字節(jié)的形式讀取后,查詢編碼表看具體使用哪種編碼方式,查到以后再進(jìn)行文件的輸出,所以字符流是字節(jié)流+查編碼表的封裝形式。
二,流的頂層基類
所有流的操作無非兩種形式:讀與寫;所以Java便所這兩種操作形式抽取出了字節(jié)流與字符流的兩種頂層的基類
字節(jié)流的頂層基類:InputStream與OutputStream
字符流的頂層基類:Read與Write
三,字符流FileWriter

1 public static void function_demo1() throws IOException { 2 // 創(chuàng)建字符寫入流對(duì)象,接收一個(gè)要寫入的文件路徑對(duì)象,此文件若不存在則新創(chuàng)建一個(gè)文件,若已存在則覆蓋的文件 3? ? ? ? FileWriter fw = new FileWriter("demo1.txt"); 4? ? ? ? fw.write("abcdefg");// 把內(nèi)容寫入緩沖區(qū) 5? ? ? ? fw.flush();// 從緩沖區(qū)把內(nèi)容刷入文件中 6? ? ? ? fw.close();// 關(guān)閉流 7? ? }

注:以上代碼中fw.flush()是把內(nèi)容從緩沖區(qū)刷入到文件中去,但是fw.close()方法是先把內(nèi)容從緩沖區(qū)刷入到文件中去即先調(diào)用flush方法,所以fw.flush()可以不用
FileWrite在寫時(shí)的換行與續(xù)寫

1 // 獲取系統(tǒng)換行的符號(hào)? 2 private static final String LINE_SEPARATOR = System.getProperty("line.separator");? 3 public static void function_demo2() throws IOException {? 4? ? ? ? FileWriter writer = new FileWriter("demo.txt", true);// 創(chuàng)建寫入流對(duì)象? 5 // 把內(nèi)容寫入到緩沖區(qū)? 6? ? ? ? writer.write("abcdef綿" + LINE_SEPARATOR + "中國(guó)人啊吼叫職了");? 7 // 把緩沖區(qū)里的內(nèi)容刷入到文件系統(tǒng)中? 8 // writer.flush();? 9 // 關(guān)閉流,在關(guān)閉之前會(huì)先把緩沖區(qū)里的內(nèi)容刷入到文件系統(tǒng)然后才關(guān)閉流;若用此關(guān)閉流可不用手動(dòng)調(diào)用flush 10? ? ? ? writer.close(); 11? ? }

注:FileWriter在支持續(xù)寫的時(shí)候提供了一個(gè)帶兩個(gè)參數(shù)的構(gòu)造函數(shù),當(dāng)傳遞為true時(shí)即可支持續(xù)寫;換行可調(diào)用系統(tǒng)提供的換行符號(hào)
四,字符流FileReader

1 public static void function_demo3() throws IOException {? 2 // 創(chuàng)建讀取流對(duì)象,指定需要讀取的文件地址? 3? ? ? ? FileReader reader = new FileReader("demo.txt");? 4 // 聲明一個(gè)變量接收讀取到的字符? 5 int ch;? 6 // 調(diào)用read方法讀取文件中的字符,當(dāng)讀取到文件的末尾的時(shí)候read方法返回-1? 7 while ((ch = reader.read()) != -1) {? 8? ? ? ? ? ? System.out.println((char) ch);? 9? ? ? ? } 10 // 關(guān)閉流 11? ? ? ? reader.close(); 12? ? }

注:此讀取方式為一個(gè)字符的讀取,每讀取一個(gè)字符便寫到控制臺(tái),以下代碼演示高效的讀取,即聲明一個(gè)緩沖區(qū)的數(shù)組,把每次所讀到的內(nèi)容先放入緩沖數(shù)組中去,然后再一次性寫到文件中

1 public static void function_demo4() throws IOException {? 2 //讀取流對(duì)象? 3? ? ? ? FileReader reader = new FileReader("demo.txt");? 4 //每次讀取到的字符放入的緩沖數(shù)組區(qū)? 5 char[] buf = new char[1024];? 6 //每次讀取到的字符數(shù)? 7 int i;? 8 //循環(huán)讀取,每次read一次把讀取到的內(nèi)容放入buf字符數(shù)組,讀到最后會(huì)返回-1? 9 while ((i = reader.read(buf)) != -1) { 10 //把讀取到的字符轉(zhuǎn)為字符串,每次轉(zhuǎn)換的數(shù)量為讀取到的字符數(shù) 11? ? ? ? ? ? System.out.println(new String(buf, 0, i)); 12? ? ? ? } 13? ? ? ? reader.close(); 14? ? }

下面用兩種方式實(shí)現(xiàn)文件的復(fù)制功能

private static void function_demo5() throws IOException {? ? ? ? FileReader fr = new FileReader("demo.txt");//創(chuàng)建讀取流對(duì)象? ? ? ? FileWriter fw = new FileWriter("demo2.txt");//創(chuàng)建寫入流對(duì)象,若文件不存在則創(chuàng)建;若存在則覆蓋 int ch;//存儲(chǔ)讀取到的字符? ? ? ? //循環(huán)讀取文件中的數(shù)據(jù) while ((ch = fr.read()) != -1) {? ? ? ? ? ? fw.write(ch);//把每次讀到的內(nèi)容寫入到新文件中? ? ? ? }? ? ? ? fw.close();//關(guān)閉? ? ? ? fr.close();//關(guān)閉? ? }

高效的復(fù)制方式

1 private static void function_demo6() throws IOException {? 2? ? ? ? FileReader fr = new FileReader("demo.txt");// 創(chuàng)建讀取流對(duì)象? 3? ? ? ? FileWriter fw = new FileWriter("demo3.txt");// 創(chuàng)建寫入流對(duì)象,若文件不存在則創(chuàng)建,若存在則覆蓋? 4 char[] buf = new char[4096];//緩存數(shù)組? 5 int ch;// 存儲(chǔ)讀取到的字符? 6 // 循環(huán)讀取文件中的數(shù)據(jù)? 7 while ((ch = fr.read(buf)) != -1) {//把每次讀取到的內(nèi)容放入緩存數(shù)組中? 8? ? ? ? ? ? fw.write(buf, 0, ch);//從緩存數(shù)組中把內(nèi)容讀出來? 9? ? ? ? } 10? ? ? ? fw.close();//關(guān)閉流 11? ? ? ? fr.close();//關(guān)閉流 12? ? }

五,高效的讀取流BufferedReader 從字符輸入流中讀取文本,緩沖各個(gè)字符,從而實(shí)現(xiàn)字符、數(shù)組和行的高效讀取。注意,此類可以直接讀取行,由此也說明此類是專門為高效的讀取文件數(shù)據(jù)的方式

1 private static void function_demo7() throws IOException { 2? ? ? ? FileReader fr = new FileReader("demo.txt");//讀取流對(duì)象 3? ? ? ? BufferedReader bReader = new BufferedReader(fr);//緩沖讀取流對(duì)象,需要傳入讀取Reader的實(shí)現(xiàn)類 4 int ch; 5 while ((ch = bReader.read()) != -1) {//此read為增強(qiáng)了的read方法,用的裝飾器模式 6? ? ? ? ? ? System.out.println((char) ch); 7? ? ? ? } 8? ? ? ? bReader.close();//關(guān)閉該流并釋放與之關(guān)聯(lián)的所有資源;即也把讀取流的對(duì)象fr給關(guān)閉了,不需要再手動(dòng)調(diào)用fr.close() 9? ? }

帶緩沖數(shù)組的讀取方式

1 private static void function_demo7() throws IOException {? 2? ? ? ? FileReader fr = new FileReader("demo.txt");// 讀取流對(duì)象? 3? ? ? ? BufferedReader bReader = new BufferedReader(fr);// 緩沖讀取流對(duì)象,需要傳入讀取Reader的實(shí)現(xiàn)類? 4 int ch = 0;? 5 char[] buff = new char[1024];? 6 while ((ch = bReader.read(buff)) != -1) {// 此read為增強(qiáng)了的read方法,用的裝飾器模式? 7? ? ? ? ? ? System.out.println(new String(buff, 0, ch));? 8? ? ? ? }? 9? ? ? ? bReader.close();// 關(guān)閉該流并釋放與之關(guān)聯(lián)的所有資源;即也把讀取流的對(duì)象fr給關(guān)閉了,不需要再手動(dòng)調(diào)用fr.close() 10? ? }

讀取行

1 private static void function_demo8() throws IOException { 2? ? ? ? FileReader fr = new FileReader("demo.txt"); 3? ? ? ? BufferedReader bReader = new BufferedReader(fr); 4? ? ? ? String line = null;//獲取每次讀到的行內(nèi)容 5 while ((line = bReader.readLine()) != null) {//如果讀取到了最后,則返回null 6? ? ? ? ? ? System.out.println(line); 7? ? ? ? } 8? ? ? ? bReader.close(); 9? ? }

六,高效的寫入流BufferedWriter
將文本寫入字符輸出流,緩沖各個(gè)字符,從而提供單個(gè)字符、數(shù)組和字符串的高效寫入。此流寫入的時(shí)候提供了一個(gè)newLine方法,可換行。

1 private static void function_demo9() throws IOException { 2? ? ? ? FileWriter fw = new FileWriter("demo4.txt"); 3? ? ? ? BufferedWriter bw = new BufferedWriter(fw); 4? ? ? ? bw.write("LioneTree"); 5? ? ? ? bw.newLine(); 6? ? ? ? bw.write("go kb go kb? nnw huo kb "); 7? ? ? ? bw.close(); 8? ? }

七,使用BufferedReader與BufferedWriter實(shí)現(xiàn)文件復(fù)制的功能

1 private static void function_demo10() throws IOException {? 2? ? ? ? FileReader fReader = new FileReader("demo.txt");//讀取流對(duì)象? 3? ? ? ? BufferedReader bReader = new BufferedReader(fReader);//緩沖讀取流對(duì)象,傳入fReader讀取流對(duì)象? 4? ? ? ? FileWriter fWriter = new FileWriter("demo5.txt");//寫入流對(duì)象? 5? ? ? ? BufferedWriter bWriter = new BufferedWriter(fWriter);//緩沖寫入流對(duì)象,傳入bWriter寫入流對(duì)象? 6? ? ? ? String line=null;//存儲(chǔ)每次讀取到的行內(nèi)容? 7 while((line=bReader.readLine())!=null) {//如果文件內(nèi)容讀完了則返回null? 8? ? ? ? ? ? bWriter.write(line);//寫入讀取到的每行內(nèi)容? 9? ? ? ? ? ? bWriter.newLine();//每讀完一行則換行 10? ? ? ? } 11? ? ? ? bReader.close();//關(guān)閉讀取流對(duì)象 12? ? ? ? bWriter.close();//關(guān)閉寫入流對(duì)象 13? ? }

八,跟蹤行號(hào)的緩沖字符輸入流LineNumberReader
此類定義了方法 setLineNumber(int) 和 getLineNumber(),它們可分別用于設(shè)置和獲取當(dāng)前行號(hào);字繼承自BufferedReader類

1 private static void function_demo11() throws IOException {? 2? ? ? ? FileReader fr = new FileReader("demo.txt");// 讀取流對(duì)象? 3? ? ? ? LineNumberReader lnr = new LineNumberReader(fr);// 行號(hào)讀取流對(duì)象,需要傳入讀取流fr對(duì)象? 4? ? ? ? String line = null;// 存儲(chǔ)讀取到的內(nèi)容? 5? ? ? ? lnr.setLineNumber(100);// 設(shè)置起始行號(hào),若不設(shè)置默認(rèn)從0開始,在讀取到的每一行的末尾處自增1? 6 while ((line = lnr.readLine()) != null) {// 按行讀取? 7? ? ? ? ? ? System.out.println(lnr.getLineNumber() + "? " + line);? 8? ? ? ? }? 9? ? ? ? lnr.close(); 10? ? }

歡迎工作一到五年的Java工程師朋友們加入Java群: 891219277
群內(nèi)提供免費(fèi)的Java架構(gòu)學(xué)習(xí)資料(里面有高可用、高并發(fā)、高性能及分布式、Jvm性能調(diào)優(yōu)、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個(gè)知識(shí)點(diǎn)的架構(gòu)資料)合理利用自己每一分每一秒的時(shí)間來學(xué)習(xí)提升自己,不要再用"沒有時(shí)間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個(gè)交代!