1 - IO

IO流次日

今日內容

字節流數組

字符流函數


字節流

在前面的學習過程當中,咱們一直都是在操做文件或者文件夾,並無給文件中寫任何數據。如今咱們就要開始給文件中寫數據,或者讀取文件中的數據學習


字節輸出流OutputStream

OutputStream此抽象類,是表示輸出字節流的全部類的超類。操做的數據都是字節,定義了輸出字節流的基本共性功能方法ui

輸出流中定義都是寫write方法編碼

image


FileOutputStream類

OutputStream有不少子類,其中子類FileOutputStream可用來寫入數據到文件spa

FileOutputStream類,即文件輸出流,是用於將數據寫入 File的輸出流code

  • 構造方法

image


FileOutputStream類寫入數據到文件中

  • 將數據寫到文件中,代碼演示
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,就會在文件末位繼續添加對象

  • 構造方法

image

  • 給文件中續寫數據和換行,代碼演示
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異常處理

在前面編寫代碼中都發生了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此抽象類,是表示字節輸入流的全部類的超類。,定義了字節輸入流的基本共性功能方法

image

  • int read():讀取一個字節並返回,沒有字節返回-1
  • int read(byte[]): 讀取必定量的字節數,並存儲到字節數組中,返回讀取到的字節數

FIleInputStream 類

InputStream有不少子類,其中子類FileInputStream可用來讀取文件內容

FileInputStream 從文件系統中的某個文件中得到輸入字節

  • 構造方法

image


FileInputStream類讀取數據read方法

在讀取文件中的數據時,調用read方法,實現從文件中讀取數據

image

  • 從文件中讀取數據,代碼演示
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(byte[])方法

在讀取文件中的數據時,調用read方法,每次只能讀取一個,太麻煩了,因而咱們能夠定義數組做爲臨時的存儲容器,這時能夠調用重載的read方法,一次能夠讀取多個字符

image

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(); } } 

字節流練習

既然會了文件的讀和寫操做了,那麼咱們就要在這個基礎上進行更爲複雜的操做。使用讀寫操做完成文件的複製

複製文件

原理: 讀取一個已有的數據,並將這些讀到的數據寫入到另外一個文件中

image

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表。其中就是各類英文字符對應的編碼

  • 編碼表:其實就是生活中字符和計算機二進制的對應關係表
    • 1.ASCII: 一個字節中的7位就能夠表示。對應的字節都是正數。0-xxxxxxx
    • ISO-8859-1 一個字節用的8位。1-xxxxxxx 負數
    • GB2312:簡體中文碼錶。包含6000-7000箇中文和符號。用兩個字節表示。兩個字節第一個字節是負數,第二個字節多是正數
      • GBK:目前最經常使用的中文碼錶,2萬的中文和符號。用兩個字節表示,其中的一部分文字,第一個字節開頭是1,第二字節開頭是0
      • GB18030:最新的中文碼錶,目前尚未正式使用
    • UNICODE : 國際標準碼錶:不管是什麼文字,都用兩個字節存儲
      • Java中的char類型用的就是這個碼錶。char c = 'a';佔兩個字節
      • Java中的字符串是按照系統默認碼錶來解析的。簡體中文版 字符串默認的碼錶是GBK
    • UTF-8:基於unicode,一個字節就能夠存儲數據,不要用兩個字節存儲,並且這個碼錶更加的標準化,在每個字節頭加入了編碼信息
能識別中文的碼錶:GBK、UTF-8;正由於識別中文碼錶不惟一,涉及到了編碼解碼問題。 對於咱們開發而言;常見的編碼 GBK UTF-8 ISO-8859-1 文字--->(數字) :編碼。 「abc」.getBytes() byte[] (數字)--->文字 : 解碼。 byte[] b={97,98,99} new String(b) 

字符輸入流Reader

上述程序中咱們讀取擁有中文的文件時,使用的字節流在讀取,那麼咱們讀取到的都是一個一個字節。只要把這些字節去查閱對應的編碼表,就可以獲得與之對應的字符。API中是否給咱們已經提供了讀取相應字符的功能流對象,Reader,讀取字符流的抽象超類

image

  • read():讀取單個字符並返回
  • read(char[]):將數據讀取到數組中,並返回讀取的個數

FileReader類

查閱FileInputStream的API,發現FileInputStream 用於讀取諸如圖像數據之類的原始字節流。要讀取字符流,請考慮使用 FileReader

打開FileReader的API介紹。用來讀取字符文件的便捷類。此類的構造方法假定默認字符編碼和默認字節緩衝區大小都是適當的

  • 構造方法

image


FileReader讀取包含中中文的文件

  • 使用FileReader讀取包含中文的文件
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(); } } 

字符輸入流Writer

既然有專門用於讀取字符的流對象,那麼確定也有寫的字符流對象,查閱API,發現有一個Writer類,Writer是寫入字符流的抽象類。其中描述了相應的寫的動做

image


FileWriter類

查閱FileOutputStream的API,發現FileOutputStream用於寫入諸如圖像數據之類的原始字節的流。要寫入字符流,請考慮使用 FileWriter

打開FileWriter的API介紹。用來寫入字符文件的便捷類.

  • 構造方法

image


FileWriter寫入中文到文件中

  • 寫入字符到文件中,先進行流的刷新,再進行流的關閉
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完成刷新並關閉


字符流練習

複製文本文件

  • 思路
    • 既然是文本涉及編碼表。須要用字符流
    • 操做的是文件。涉及硬盤
    • 有指定碼錶嗎?沒有,默認就行
    • 操做的是文件,使用的 默認碼錶。使用哪一個字符流對象。直接使用字符流操做文件的便捷類。FileReader FileWriter
    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(); } } 

總結

知識點總結

  • IO分類
    • |- 字節流
      • |- 字節輸入流InputStream抽象類
        • |- FileInputStream 操做文件的字節流
      • |- 字節輸入流OutputStream 抽象類
        • |- FileOutputStream操做文件的字節輸入流
    • |- 字符流
      • |- 字符輸入流Reader抽象類
        • InputStreamReader 輸入操做的轉換流
          • |- FileReader 用來操做文件的字符輸入流(簡便的流)
      • |- 字符輸入流Writer抽象類
        • OutputStreamWriter 輸出操做的轉換流
          • |- FileWriter 用來操做文件的字符輸出流(簡便的流)
相關文章
相關標籤/搜索