
注:FileReader繼承InputStreamReader類,InputStreamReader實現Reader接口,其他同理。
對於文件內容的操作主要分為兩大類
分別是:
字符流
字節流
其中,字符流有兩個抽象類:Writer Reader
其對應子類FileWriter和FileReader可實現文件的讀寫操作
BufferedWriter和BufferedReader能夠提供緩沖區功能,用以提高效率
同樣,字節流也有兩個抽象類:InputStream OutputStream
其對應子類有FileInputStream和FileOutputStream實現文件讀寫
BufferedInputStream和BufferedOutputStream提供緩沖區功能
字符流和字節流的主要區別:
1.字節流讀取的時候,讀到一個字節就返回一個字節; 字符流使用了字節流讀到一個或多個字節(中文對應的字節數是兩個,在UTF-8碼表中是3個字節)時。先去查指定的編碼表,將查到的字符返回。
2.字節流可以處理所有類型數據,如:圖片,MP3,AVI視頻文件,而字符流只能處理字符數據。只要是處理純文本數據,就要優先考慮使用字符流,除此之外都用字節流。
注意:
讀寫流使用完都要用.close方法關閉,防止占用資源,但是在關閉之前防止空值最好做空值判斷再關閉;進行寫操作時想立即生效用write.flush()刷新。
注意寫文件路徑時盤符后面用\\或者/,如:c:\\demo.txt或者c:/demo.txt
BufferedReader特有方法:readLine(),將行標記之前的數據作為字符串返回,讀到結尾時返回null,讀取行是將讀取的字符臨時存儲產生的效果。
具體操作方法如下:
FileReader(字符流的讀取)
FileReader r = new FileReader(path); //方式一:讀取單個字符的方式 //每讀取一次,向下移動一個字符單位,返回讀取的字節數 int temp1 = r.read(); System.out.println((char)temp1); int temp2 = r.read(); System.out.println((char)temp2); //方式二:循環讀取 //read()方法讀到文件末尾會返回-1 /* while (true) { int temp = r.read(); if (temp == -1) { break; } System.out.print((char)temp); } */ //方式三:循環讀取的簡化操作 //單個字符讀取,當temp不等於-1的時候打印字符 /*int temp = 0; while ((temp = r.read()) != -1) { System.out.print((char)temp); } */ //方式四:讀入到字符數組 /* char[] buf = new char[1024]; int temp = r.read(buf); //將數組轉化為字符串打印,后面參數的意思是 //如果字符數組未滿,轉化成字符串打印后尾部也許會出現其他字符 //因此,讀取的字符有多少個,就轉化多少為字符串 System.out.println(new String(buf,0,temp)); */ //方式五:讀入到字符數組的優化 //由於有時候文件太大,無法確定需要定義的數組大小 //因此一般定義數組長度為1024,采用循環的方式讀入 /* char[] buf = new char[1024]; int temp = 0; while((temp = r.read(buf)) != -1) { System.out.print(new String(buf,0,temp)); } */ FileWriter(字符流的寫入) String path="E:\\demo.txt"; //由於IO操作會拋出異常,因此在try語句塊的外部定義FileWriter的引用 FileWriter w = null; try { //以path為路徑創建一個新的FileWriter對象 //如果需要追加數據,而不是覆蓋,則使用FileWriter(path,true)構造方法 w = new FileWriter(path); //將字符串寫入到流中,\r\n表示換行想有好的 w.write("Nerxious is a good boy\r\n"); //如果想馬上看到寫入效果,則需要調用w.flush()方法 w.flush(); } catch (IOException e) { e.printStackTrace(); } finally { //如果前面發生異常,那么是無法產生w對象的 //因此要做出判斷,以免發生空指針異常 if(w != null) { try { //關閉流資源,需要再次捕捉異常 w.close(); } catch (IOException e) { e.printStackTrace(); } } } 即FileWriter w = new FileWriter(path);//指定寫的路徑 w.write("Nerxious is a good boy\r\n");//寫入具體內容 文本文件的復制 String doc=”...”; String copy=”...”: FileReader r= new FileReader(doc); FileWriter w = new FileWriter(copy); //方式一:單個字符寫入 int temp = 0; while((temp = r.read()) != -1) { w.write(temp); } //方式二:字符數組方式寫入 /* char[] buf = new char[1024]; int temp = 0; while ((temp = r.read(buf)) != -1) { w.write(new String(buf,0,temp)); } */ 利用字符流的緩沖區來進行文本文件的復制 FileReader r = new FileReader(doc); FileWriter w = new FileWriter(copy); //創建緩沖區對象 //將需要提高效率的FileReader和FileWriter對象放入其構造函數內 //當然,也可以使用匿名對象的方式 br = new BufferedReader(new FileReader(doc)); BufferedReader br = new BufferedReader(r); BufferedWriter bw = new BufferedWriter(w); String line = null; //讀取行,直到返回null //readLine()方法只返回換行符之前的數據 while((line = br.readLine()) != null) { //使用BufferWriter對象的寫入方法 bw.write(line); //寫完文件內容之后換行 //newLine()方法依據平台而定 //windows下的換行是\r\n //Linux下則是\n bw.newLine(); } 字節流: FileOutputStream(字符流的寫入) FileOutputStream o = new FileOutputStream(path); String str = "Nerxious is a good boy\r\n"; byte[] buf = str.getBytes(); //也可以直接使用o.write("String".getBytes()); //因為字符串就是一個對象,能直接調用方法 o.write(buf); FileInputStream(字節流的讀取) FileInputStream i = new FileInputStream(path); //方式一:單個字符讀取 //需要注意的是,此處我用英文文本測試效果良好 //但中文就悲劇了,不過下面兩個方法效果良好 int ch = 0; while((ch=i.read()) != -1){ System.out.print((char)ch); } //方式二:數組循環讀取 /* byte[] buf = new byte[1024]; int len = 0; while((len = i.read(buf)) != -1) { System.out.println(new String(buf,0,len)); } */ //方式三:標准大小的數組讀取 /* //定一個一個剛好大小的數組 //available()方法返回文件的字節數 //但是,如果文件過大,內存溢出,那就悲劇了 //所以,親們要慎用!!!上面那個方法就不錯 byte[] buf = new byte[i.available()]; i.read(buf); //因為數組大小剛好,所以轉換為字符串時無需在構造函數中設置起始點 System.out.println(new String(buf)); */ 二進制文件(即非純文本文件)的復制 Bin/copy為 文件路徑,“E:\\demo.mp3”,此處示例文件為mp3文件 FileInputStream i = null; FileOutputStream o = null; try { i = new FileInputStream(bin); o = new FileOutputStream(copy); //循環的方式讀入寫出文件,從而完成復制 byte[] buf = new byte[1024]; int temp = 0; while((temp = i.read(buf)) != -1) { o.write(buf, 0, temp); } 利用字節流的緩沖區進行二進制文件的復制 FileInputStream i = null; FileOutputStream o = null; BufferedInputStream bi = null; BufferedOutputStream bo = null; try { i = new FileInputStream(bin); o = new FileOutputStream(copy); bi = new BufferedInputStream(i); bo = new BufferedOutputStream(o); byte[] buf = new byte[1024]; int temp = 0; while((temp = bi.read(buf)) != -1) { bo.write(buf,0,temp); } 文件的操作 遞歸列出目錄下所有文件 File f = new File(path); //方式一:list() //返回一個包含指定目錄下所有文件名的字符串數組 //如果不是一個目錄則返回null String[] files = f.list(); for (String x : files) { System.out.println(x); } //方式二: if(f.isDirectory()){ File[] files = f.listFiles(); for(File x : files) { print(x); } } 兩者都是返回目錄下的所有文件名,但是第二種方式更實用,為遞歸列出文件做鋪墊 列出根目錄: //listRoots()是一個靜態方法,返回文件數組 File[] files = File.listRoots(); //foreach循環打印File對象 for (File x : files) { System.out.println(x); } 本地環境是Linux,所以根目錄只有一個 /,如果是Windows就能列出你的所有盤符 Scanner類: 從鍵盤讀取 Scanner input = new Scanner(System.in); System.out.println("請輸出一個整數:"); int i = input.nextInt(); System.out.println("你輸入的整數是:" + i); 從字符串讀取 Scanner input = new Scanner("hello\r\nworld\r\n"); //循環讀取,hasNext()方法和集合框架里面的一樣使 while(input.hasNext()) { //每次讀取一行,別的讀取方法見API,比較簡單 String s = input.nextLine(); System.out.println(s); } 從文件讀取: File f = new File(path); //從文件構造Scanner對象,有可能產生異常 Scanner input = new Scanner(f); while(input.hasNext()) { String s = input.nextLine(); System.out.println(s); } PrintWriter類 向文件寫入內容 File file = new File(path); //此處構造函數還可以傳其他對象,具體參考API文檔 PrintWriter p = new PrintWriter(file); //向文件寫入一行,此外還有print()和printf()方法 p.println("如果有一天我回到從前"); p.println("回到最原始的我"); p.println("你是否會覺得我不錯"); //刷新流 p.flush(); 與PrintWriter類似的還有一個PrintStream類,此處以PrintWriter舉例是因為文本文件具有人為可讀性,而二進制文件(字節模式)則需要使用專門的程序來讀取.可能有人會問:FileOutputStream、 FileWriter都能寫文件,那么為何還需要PrintWriter和PrintStream類,如果細看API文檔,可以知道前者單純的字符寫入流和字節寫入流操作的方式大多用數組進行,對文件的細化處理非常不方便,而PrintWriter和PrintStream則很好的解決了這一問題,提供print()等方法,並且,PrintWriter和PrintStream對於不存在文件對象的情況下會直接創建,如果已有文件對象,它們則會把原有文件給覆蓋掉,卻沒有增加方法。解決這問題也很簡單,再看API文檔,PrintWriter有一個構造方法PrintWriter(Writer out),也就是能夠傳入Writer對象,PrintStream有一個構造方法PrintStream(OutputStream out),也就是能傳入OutputStream對象。因此,我們這樣寫就可以了 new PrintWriter(new FileWriter(file,true)) new PrintStream(new FileOutputStream(file,true)) 既能增加數據,也能更高效的處理文件,見如下代碼示范 File file = new File(path); //利用FileWriter方式構建PrintWriter對象,實現追加 PrintWriter p = new PrintWriter(new FileWriter(file,true)); p.println("尼瑪 這一句就是追加的 看到沒"); p.flush(); System類相關: //別忘了,OutputStream是所有字節寫入流的父類 OutputStream out = System.out; //寫入數據,只能是數組,所以用getBytes()方法 out.write("Hello,bitch!\r\n".getBytes()); System類中的讀取 InputStream in = System.in; System.out.print("請輸入文字: "); byte[] buf = new byte[1024]; int len = 0; //將輸入的數據保證到數組中,len記錄輸入的長度 len = in.read(buf); //用字符串的方式打印數組中的數據 System.out.println("你的輸入是: " + new String(buf,0,len)); 利用BufferedReader實現對鍵盤的讀取 BufferedReader b = new BufferedReader(new InputStreamReader(System.in)); System.out.print("請輸入文本:"); String str = b.readLine(); System.out.println("你輸入的是:" + str); //循環讀取方式 /* while(true) { System.out.print("請輸入文本:"); String str = b.readLine(); //如果輸入over就結束循環 if("over".equals(str)) { break; } System.out.println("你輸入的是:" + str);
