字節流數組
字符流函數
在前面的學習過程當中,咱們一直都是在操做文件或者文件夾,並無給文件中寫任何數據。如今咱們就要開始給文件中寫數據,或者讀取文件中的數據學習
OutputStream此抽象類,是表示輸出字節流的全部類的超類。操做的數據都是字節,定義了輸出字節流的基本共性功能方法ui
輸出流中定義都是寫write方法編碼
OutputStream有不少子類,其中子類FileOutputStream可用來寫入數據到文件spa
FileOutputStream類,即文件輸出流,是用於將數據寫入 File的輸出流code
public class FileOutputStreamDemo { public static void main(String[] args) throws IOException { //需求:將數據寫入到文件中。 //建立存儲數據的文件。 File file = new File("c:\\file.txt"); //建立一個用於操做文件的字節輸出流對象。一建立就必須明確數據存儲目的地。 //輸出流目的是文件,會自動建立。若是文件存在,則覆蓋。 FileOutputStream fos = new FileOutputStream(file); //調用父類中的write方法。 byte[] data = "abcde".getBytes(); fos.write(data); //關閉流資源。 fos.close(); } }
咱們直接new FileOutputStream(file)這樣建立對象,寫入數據,會覆蓋原有的文件,那麼咱們想在原有的文件中續寫內容怎麼辦呢?xml
繼續查閱FileOutputStream的API。發如今FileOutputStream的構造函數中,能夠接受一個boolean類型的值,若是值true,就會在文件末位繼續添加對象
public class FileOutputStreamDemo2 { public static void main(String[] args) throws Exception { File file = new File("c:\\file.txt"); FileOutputStream fos = new FileOutputStream(file, true); String str = "\r\n"+"HelloIO"; fos.write(str.getBytes()); fos.close(); } }
在前面編寫代碼中都發生了IO的異常。咱們在實際開發中,對異常時如何處理的,咱們來演示一下blog
public class FileOutputStreamDemo3 { public static void main(String[] args) { File file = new File("c:\\file.txt"); //定義FileOutputStream的引用 FileOutputStream fos = null; try { //建立FileOutputStream對象 fos = new FileOutputStream(file); //寫出數據 fos.write("abcde".getBytes()); } catch (IOException e) { System.out.println(e.toString() + "----"); } finally { //必定要判斷fos是否爲null,只有不爲null時,才能夠關閉資源 if (fos != null) { try { fos.close(); } catch (IOException e) { throw new RuntimeException(""); } } } } }
經過前面的學習,咱們能夠把內存中的數據寫出到文件中,那如何想把內存中的數據讀到內存中,咱們經過InputStream能夠實現。InputStream此抽象類,是表示字節輸入流的全部類的超類。,定義了字節輸入流的基本共性功能方法
InputStream有不少子類,其中子類FileInputStream可用來讀取文件內容
FileInputStream 從文件系統中的某個文件中得到輸入字節
在讀取文件中的數據時,調用read方法,實現從文件中讀取數據
public class FileInputStreamDemo { public static void main(String[] args) throws IOException { File file = new File("c:\\file.txt"); //建立一個字節輸入流對象,必須明確數據源,其實就是建立字節讀取流和數據源相關聯。 FileInputStream fis = new FileInputStream(file); //讀取數據。使用 read();一次讀一個字節。 int ch = 0; while((ch=fis.read())!=-1){ System.out.println("ch="+(char)ch); } // 關閉資源。 fis.close(); } }
在讀取文件中的數據時,調用read方法,每次只能讀取一個,太麻煩了,因而咱們能夠定義數組做爲臨時的存儲容器,這時能夠調用重載的read方法,一次能夠讀取多個字符
public class FileInputStreamDemo2 { public static void main(String[] args) throws IOException { /* * 演示第二個讀取方法, read(byte[]); */ File file = new File("c:\\file.txt"); // 建立一個字節輸入流對象,必須明確數據源,其實就是建立字節讀取流和數據源相關聯。 FileInputStream fis = new FileInputStream(file); //建立一個字節數組。 byte[] buf = new byte[1024];//長度能夠定義成1024的整數倍。 int len = 0; while((len=fis.read(buf))!=-1){ System.out.println(new String(buf,0,len)); } fis.close(); } }
既然會了文件的讀和寫操做了,那麼咱們就要在這個基礎上進行更爲複雜的操做。使用讀寫操做完成文件的複製
原理: 讀取一個已有的數據,並將這些讀到的數據寫入到另外一個文件中
public class CopyFileTest { public static void main(String[] args) throws IOException { //1,明確源和目的。 File srcFile = new File("c:\\YesDir\test.JPG"); File destFile = new File("copyTest.JPG"); //2,明確字節流 輸入流和源相關聯,輸出流和目的關聯。 FileInputStream fis = new FileInputStream(srcFile); FileOutputStream fos = new FileOutputStream(destFile); //3, 使用輸入流的讀取方法讀取字節,並將字節寫入到目的中。 int ch = 0; while((ch=fis.read())!=-1){ fos.write(ch); } //4,關閉資源。 fos.close(); fis.close(); } }
上述代碼輸入流和輸出流之間是經過ch這個變量進行數據交換的
上述複製文件有個問題,每次都從源文件讀取一個,而後在寫到指定文件,接着再讀取一個字符,而後再寫一個,一直這樣下去。效率極低
上述代碼複製文件效率過低了,而且頻繁的從文件讀數據,和寫數據,能不能一次多把文件中多個數據都讀進內容中,而後在一次寫出去,這樣的速度必定會比前面代碼速度快
public class CopyFileByBufferTest { public static void main(String[] args) throws IOException { File srcFile = new File("c:\\YesDir\test.JPG"); File destFile = new File("copyTest.JPG"); // 明確字節流 輸入流和源相關聯,輸出流和目的關聯。 FileInputStream fis = new FileInputStream(srcFile); FileOutputStream fos = new FileOutputStream(destFile); //定義一個緩衝區。 byte[] buf = new byte[1024]; int len = 0; while ((len = fis.read(buf)) != -1) { fos.write(buf, 0, len);// 將數組中的指定長度的數據寫入到輸出流中。 } // 關閉資源。 fos.close(); fis.close(); } }
通過前面的學習,咱們基本掌握的文件的讀寫操做,在操做過程當中字節流能夠操做全部數據,但是當咱們操做的文件中有中文字符,而且須要對中文字符作出處理時怎麼辦呢?
經過如下程序讀取帶有中文件的文件
public class CharStreamDemo { public static void main(String[] args) throws IOException { //給文件中寫中文 writeText(); //讀取文件中的中文 readText(); } //讀取中文 public static void readText() throws IOException { FileInputStream fis = new FileInputStream("c:\\a.txt"); int ch = 0; while((ch = fis.read())!=-1){ System.out.println(ch); } } //寫中文 public static void writeText() throws IOException { FileOutputStream fos = new FileOutputStream("c:\\a.txt"); fos.write("好再來a".getBytes()); fos.close(); } }
上面程序在讀取含有中文的文件時,咱們並無看到具體的中文,而是看到一些數字,這是什麼緣由呢?既然看不到中文,那麼咱們如何對其中的中文作處理呢?要解決這個問題,咱們必須研究下字符的編碼過程
咱們知道計算機底層數據存儲的都是二進制數據,而咱們生活中的各類各樣的數據,如何才能和計算機中存儲的二進制數據對應起來呢?
這時老美他們就把每個字符和一個整數對應起來,就造成了一張編碼表,老美他們的編碼表就是ASCII表。其中就是各類英文字符對應的編碼
能識別中文的碼錶:GBK、UTF-8;正由於識別中文碼錶不惟一,涉及到了編碼解碼問題。 對於咱們開發而言;常見的編碼 GBK UTF-8 ISO-8859-1 文字--->(數字) :編碼。 「abc」.getBytes() byte[] (數字)--->文字 : 解碼。 byte[] b={97,98,99} new String(b)
上述程序中咱們讀取擁有中文的文件時,使用的字節流在讀取,那麼咱們讀取到的都是一個一個字節。只要把這些字節去查閱對應的編碼表,就可以獲得與之對應的字符。API中是否給咱們已經提供了讀取相應字符的功能流對象,Reader,讀取字符流的抽象超類
查閱FileInputStream的API,發現FileInputStream 用於讀取諸如圖像數據之類的原始字節流。要讀取字符流,請考慮使用 FileReader
打開FileReader的API介紹。用來讀取字符文件的便捷類。此類的構造方法假定默認字符編碼和默認字節緩衝區大小都是適當的
public class CharStreamDemo { public static void main(String[] args) throws IOException { //給文件中寫中文 writeText(); //讀取文件中的中文 readText(); } //讀取中文 public static void readText() throws IOException { FileReader fr = new FileReader("E:\\test\\a.txt"); int ch = 0; while((ch = fr.read())!=-1){ //輸出的字符對應的編碼值 System.out.println(ch); //輸出字符自己 System.out.println((char)ch); } } //寫中文 public static void writeText() throws IOException { FileOutputStream fos = new FileOutputStream("E:\\test\\a.txt"); fos.write("林子很大".getBytes()); fos.close(); } }
既然有專門用於讀取字符的流對象,那麼確定也有寫的字符流對象,查閱API,發現有一個Writer類,Writer是寫入字符流的抽象類。其中描述了相應的寫的動做
查閱FileOutputStream的API,發現FileOutputStream用於寫入諸如圖像數據之類的原始字節的流。要寫入字符流,請考慮使用 FileWriter
打開FileWriter的API介紹。用來寫入字符文件的便捷類.
public class FileWriterDemo { public static void main(String[] args) throws IOException { //演示FileWriter 用於操做文件的便捷類。 FileWriter fw = new FileWriter("E:\\text\\fw.txt"); fw.write("你好謝謝再見");//這些文字都要先編碼。都寫入到了流的緩衝區中。 fw.flush();//刷新 fw.close();// 關閉以前須要刷新它 } }
flush():將流中的緩衝區緩衝的數據刷新到目的地中,刷新後,流還能夠繼續使用
close():關閉資源,但在關閉前會將緩衝區中的數據先刷新到目的地,不然丟失數據,而後在關閉流。流不可使用。若是寫入數據多,必定要一邊寫一邊刷新,最後一次能夠不刷新,由close完成刷新並關閉
複製文本文件
public class CopyTextFileTest { public static void main(String[] args) throws IOException { copyTextFile(); } public static void copyTextFile() throws IOException { //1,明確源和目的。 FileReader fr = new FileReader("c:\\a.txt"); FileWriter fw = new FileWriter("c:\\copy.txt"); //2,爲了提升效率。自定義緩衝區數組。字符數組。 char[] buf = new char[1024]; int len = 0; while((len=fr.read(buf))!=-1){ fw.write(buf,0,len); } /*2,循環讀寫操做。效率低。 int ch = 0; while((ch=fr.read())!=-1){ fw.write(ch); } */ //3,關閉資源。 fw.close(); fr.close(); } }