【Java學習筆記(十一)】之檔案IO流的要點詳細介紹

2020-08-10 12:19:20

本文章由公號【開發小鴿】發佈!歡迎關注!!!


老規矩–妹妹鎮樓:

一. File類

(一) 概述

       File類是檔案和目錄路徑名的抽象表示,即檔案和目錄通過File類封裝成物件,可以方便地處理檔案和目錄。

       對於File類而言,封裝的並不是一個真實存在的檔案,而是一個路徑名,該路徑名可能存在,也可能不存在。

(二) 構造方法


方法名 說明
File(String pathname) 通過將給定的路徑名字串轉換爲抽象路徑名來建立新的 File範例
File(String parent, String child) 從父路徑名字串和子路徑名字串建立新的 File範例
File(File parent, String child) 從父抽象路徑名和子路徑名字串建立新的 File範例

(三) 檔案目錄建立方法


方法名 說明
public boolean createNewFile() 當具有該名稱的檔案不存在時,建立一個由該抽象路徑名命名的新空檔案
public boolean mkdir() 建立由此抽象路徑名命名的目錄
public boolean mkdirs() 建立由此抽象路徑名命名的目錄,包括任何必需但不存在的父目錄

(四) 判斷和獲取方法

1. 判斷方法


方法名 說明
public boolean isDirectory() 測試此抽象路徑名錶示的File是否爲目錄
public boolean isFile() 測試此抽象路徑名錶示的File是否爲檔案
public boolean exists() 測試此抽象路徑名錶示的File是否存在

2. 獲取方法


方法名 說明
public String getAbsolutePath() 返回此抽象路徑名的絕對路徑名字串
public String getPath() 將此抽象路徑名轉換爲路徑名字串
public String getName() 返回由此抽象路徑名錶示的檔案或目錄的名稱
public String[] list() 返回此抽象路徑名錶示的目錄中的檔案和目錄的名稱字串陣列
public File[] listFiles() 返回此抽象路徑名錶示的目錄中的檔案和目錄的File物件陣列

(五) 刪除方法


方法名 說明
public boolean delete() 刪除由此抽象路徑名錶示的檔案或目錄

       注意:一個目錄中有內容,那麼不能直接刪除,要先將裏面的內容刪除,才能 纔能刪除目錄。

二. IO流

(一) 概述

       IO代表着輸入輸出,流代表着數據的傳輸。IO流用於處理裝置間的數據傳輸問題,如檔案複製,檔案上傳,檔案下載。


(二) 分類

1. 按數據的流向分

       (1)輸入流:從磁碟輸入到記憶體,即從磁碟讀數據。

       (2)輸出流:從記憶體輸出到磁碟,即寫數據到磁碟。

       注意:記憶的時候把輸入輸出都和記憶體聯繫起來,輸入流是輸入到記憶體,輸出流是從記憶體輸出。

2. 按數據型別分

       (1)位元組流

       (2)字元流

(三) IO流的使用場景


  1. 純文字檔案,優先使用字元流

  2. 圖片,視訊等二進制檔案,優先位元組流。

  3. 不能確定檔案型別,優先位元組流。


三. 位元組流


(一) 位元組流抽象基礎類別

1. InputStream

       位元組輸入流的所有類的超類

2. OutputStream

       位元組輸出流的所有類的超類

       位元組流子類名的特點:子類的名稱都是以父類別名作爲子類名的後綴。

(二) 檔案位元組輸出流

       FileOutputStream,注意後綴名是OutputStream,是該類的父類別名。

使用檔案位元組輸出流寫數據的步驟:

  1. 建立位元組輸出流物件 (呼叫系統功能建立了檔案,建立位元組輸出流物件,讓位元組輸出流物件指向檔案)

  2. 呼叫位元組輸出流物件的寫數據方法

  3. 釋放資源 (關閉此檔案輸出流並釋放與此流相關聯的任何系統資源)

(三) 檔案位元組流寫數據的問題


1. 位元組流寫數據實現換行

不同系統的換行符是不同的:

windows:\r\n
linux:\n
mac:\r

2. 實現追加寫入

public FileOutputStream(String name,boolean append)

       建立檔案輸出流以指定的名稱寫入檔案。如果第二個參數爲 true ,則位元組將寫入檔案的末尾而不是開頭

(四) 檔案位元組輸入流讀數據


1. FileInputStream

       建立檔案位元組輸入流,從磁碟檔案中讀取數據。


2. 步驟

       (1)建立位元組輸入流物件

       (2)呼叫位元組輸入流物件的讀數據方法

       (3)釋放資源

3. read(byes[] b)方法

       read方法返回的是實際讀取的位元組個數,當沒有讀取到數據時,返回-1。

 FileInputStream fis = new FileInputStream("myByteStream\\fos.txt");
    int by;
    /*
      fis.read():讀數據
      by=fis.read():把讀取到的數據賦值給by
      by != -1:判斷讀取到的數據是否是-1
    */
    while ((by=fis.read())!=-1) {
      System.out.print((char)by);
   }
//釋放資源
fis.close();

四. 位元組緩衝流


(一) 概述

1. BufferedOutputStream

       緩衝輸出流,當向磁碟中寫入數據時,先將數據寫入緩衝流中,再將緩衝流中存積的大量數據呼叫底層輸出流寫入磁碟。這樣,呼叫底層輸出流的次數減少了很多。

2. BufferedInputStream

       緩衝輸入流,同理,在底層輸入流和記憶體中搭建一個緩衝輸入流,減少呼叫底層輸入流的次數。

(二) 構造方法


1. BufferedOutputStream(OutputStream out)

       建立位元組緩衝輸出流物件,參數是輸出流物件。

2. BufferedInputStream(InputStream in)

       建立位元組緩衝輸入流物件,參數是輸入流物件。

(三) 範例


BufferedOutputStream bos = new BufferedOutputStream(new 
                  FileOutputStream("myByteStream\\bos.txt"));
    //寫數據
    bos.write("hello\r\n".getBytes());
    bos.write("world\r\n".getBytes());
    //釋放資源
    bos.close();
 
    //位元組緩衝輸入流:BufferedInputStream(InputStream in)
    BufferedInputStream bis = new BufferedInputStream(new           
                  FileInputStream("myByteStream\\bos.txt"));
    //一次讀取一個位元組數據
//    int by;
//    while ((by=bis.read())!=-1) {
//      System.out.print((char)by);
//    }
    //一次讀取一個位元組陣列數據
    byte[] bys = new byte[1024];
    int len;
    while ((len=bis.read(bys))!=-1) {
      System.out.print(new String(bys,0,len));
   }
    //釋放資源
bis.close();

五. 字元流


(一) 概述

       在位元組流操作中,中文的表示很不方便,因此,有了字元流來幫助中文等其他字元的表示。

       字元流= 位元組流 + 編碼表

       中文的表示也是用幾個位元組拼成的,通過某種規則將幾個位元組表示成一箇中文字元,這種規則就是編碼表,將各種各樣的字元用位元組表示的規則。

(二) 字元集

       前面講了,編碼表是一種字元和位元組對應的規則,那麼,首先我們需要一個龐大的字元集來儲存大量的字元。包括各國家文字、標點符號、圖形符號、數位等。

1. ASCII 字元集

       基於拉丁字母的一套電腦編碼系統,用於顯示現代英語,主要包括控制字元(回車鍵、退格、換行鍵等)和可顯示字元(英文大小寫字元、阿拉伯數位和西文符號)

       基本的ASCII字元集,使用7位表示一個字元,共128字元。ASCII的擴充套件字元集使用8位元表示一個字元,共256字元,方便支援歐洲常用字元。是一個系統支援的所有字元的集合,包括各國家文字、標點符號、圖形符號、數位等

2. GBXXX 字元集

       GBK:最常用的中文碼錶 碼表。是在GB2312標準基礎上的擴充套件規範,使用了雙位元組編碼方案,共收錄了21003個漢字,完全相容GB2312標準,同時支援繁體漢字以及日韓漢字等

3. Unicode 字元集

       爲表達任意語言的任意字元設計,是業界的一種標準,也稱爲統一碼,標準萬國碼。最多使用4個位元組的數位來表示字元,有三種編碼方案,UTF-8,UTF-16,UTF-32。

(三) 編碼表

1. UTF-8編碼

       用來表示Unicode標準中任意字元,它是電子郵件、網頁及其他儲存或傳送文字的應用中,優先採用的編碼。網際網路工程工作小組(IETF)要求所有網際網路協定都必須支援UTF-8編碼。它使用一至四個位元組爲每個字元編碼

編碼規則:

       (1)128個US-ASCII字元,只需一個位元組編碼

       (2)拉丁文等字元,需要二個位元組編碼

       (3)大部分常用字(含中文),使用三個位元組編碼

       (4)其他極少使用的Unicode輔助字元,使用四位元組編碼

(四) 字元的編碼與解碼方法


方法名 說明
byte[] getBytes() 使用平臺的預設字元集將該 String編碼爲一系列位元組
byte[] getBytes(String charsetName) 使用指定的字元集將該 String編碼爲一系列位元組
String(byte[] bytes) 使用平臺的預設字元集解碼指定的位元組陣列來建立字串
String(byte[] bytes, String charsetName) 通過指定的字元集解碼指定的位元組陣列來建立字串

package File使用;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class 字元流編碼解碼 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String s = "中國";
        byte[] bys = s.getBytes("GBK");
        String ss = new String(bys, "GBK");
        System.out.println(ss);

    }
}

(五) 字元流的編碼與解碼

1. InputStreamReader

       輸入流是爲了讀取磁碟中的數據,則InputStreamReader就是從位元組流到字元流的橋樑。讀取位元組,使用指定的編碼將位元組解碼爲字元。

2. OutputStreamWriter

       輸出流是爲了將數據寫入磁碟中,則OutputStreamWriter是字元流到位元組流的橋樑。使用指定的編碼將寫入的字元編碼爲位元組。

3. 構造方法


方法名 說明
InputStreamReader(InputStream in) 使用預設字元編碼建立InputStreamReader物件
InputStreamReader(InputStream in,String chatset) 使用指定的字元編碼建立InputStreamReader物件
OutputStreamWriter(OutputStream out) 使用預設字元編碼建立OutputStreamWriter物件
OutputStreamWriter(OutputStream out,String charset) 使用指定的字元編碼建立OutputStreamWriter物件

4. 重新整理和關閉


方法名 說明
flush() 重新整理流,之後還可以繼續寫數據
close() 關閉流,釋放資源,但是在關閉之前會先重新整理流。一旦關閉,就不能再寫數據

(六) 字元流寫數據


package File使用;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class 字元流寫 {
    public static void main(String[] args) throws IOException {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("Student\\1.txt"));

        char[] chs = {'a', 'b', 'c', 'd'};
        osw.write(chs);

        osw.write("edf");

        //寫字元
        osw.write(97);
        osw.write(98);
        osw.write(99);

        osw.close();
    }

}

(七) 字元流讀數據


package File使用;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class 字元流讀 {
    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("Student\\1.txt"));

//        int ch;
//        while((ch = isr.read()) != -1)
//        {
//            System.out.println((char)ch);
//        }
        char[] chs = new char[1024];
        int len;
        while((len=isr.read(chs)) != -1)
        {
            System.out.println(new String(chs, 0, len));
        }

        isr.close();
    }
}

(八) 字元緩衝流

1. 概述

       與位元組緩衝流一樣,都是建立緩衝區。

(1) BufferedWriter

       設定字元緩衝區,將字元寫入字元輸出流。

(2) BufferedReader

       設定字元緩衝區,從字元輸入流中讀取字元。

2. 構造方法

(1) BufferedWriter(Writer out)

       建立字元緩衝輸出流物件。

(2) BufferedReader(Reader in)

       建立字元緩衝輸入流物件

package File使用;

import java.io.*;

public class 字元緩衝 {
    public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("Student\\1.txt"));

        bw.write("hello\r\n");
        bw.close();


        BufferedReader br = new BufferedReader(new FileReader("Student\\1.txt"));
        char[] chs = new char[1024];
        int len;
        while((len=br.read(chs)) != -1)
        {
            System.out.print(new String(chs, 0, len));
        }
    }
}

3. 字元緩衝流特有方法

(1) BufferedWriter中的newLine()

       寫入一個行分隔符,且該字元的具體定義是由系統的屬性決定的。

(2) BufferedReader中的readLine()

       讀一行文字,但不包括行終止符,如果到達末尾,則返回null。

BufferedWriter bw = new BufferedWriter(new                
             FileWriter("myCharStream\\bw.txt"));
    //寫數據
    for (int i = 0; i < 10; i++) {
      bw.write("hello" + i);
      //bw.write("\r\n");
      bw.newLine();
      bw.flush();
   }
    //釋放資源
    bw.close();
    //建立字元緩衝輸入流
    BufferedReader br = new BufferedReader(new                
             FileReader("myCharStream\\bw.txt"));
    String line;
    while ((line=br.readLine())!=null) {
      System.out.println(line);
   }
br.close();

六. 複製檔案的例外處理


(一) try-catch-finally


try{
	可能出現異常的程式碼
}catch(異常類名 變數名){
	例外處理
}finally{
	所有清除操作
}

(二) JDK7改進


try(定義流物件){
	可能出現異常的程式碼
}catch(異常類名 變數名){
	例外處理
}

(三) JDK9改進


定義輸入流物件;
定義輸出流物件;
try(輸入流物件; 輸出流物件){
	可能出現異常程式碼
}catch(異常類名 變數名){
	例外處理
}

七. 標準輸入輸出流


(一) 標準輸入流

       System類中的靜態成員變數

public static final InputStream in;

       標準輸入流,通常該流對應於鍵盤輸入或由主機環境或使用者指定的另一個輸入源。

(二) 標準輸出流

       System類中的靜態成員變數

public static final PrintStream out;

       標準輸出流,通常該流對應於顯示輸出或由主機環境或使用者指定的另一個輸出目標。

通常我們所用的輸出語句就是一個標準輸出流。

System.out.println();

八. 位元組與字元列印流


(一) 位元組列印流

1. 特點

       只用於輸出數據,不會拋出IOException異常。

2. 範例

PrintStream ps = new PrintStream(1.txt」);
ps.println(97);
ps.close();

(二) 字元列印流

1. 構造方法


方法名 說明
PrintWriter(String fileName) 使用指定的檔名建立一個新的PrintWriter,而不需要自動執行重新整理
PrintWriter(Writer out, boolean autoFlush) 建立一個新的PrintWriter out:字元輸出流 autoFlush: 一個布爾值,如果爲真,則println , printf ,或format方法將重新整理輸出緩衝區

2. 範例


PrintWriter pw = new PrintWriter(1.txt」);
pw.write(「hello」);
pw.write(「\r\n」);
pw.flush();
pw.close();

PrintWriter pw2 = new PrintWriter(new FileWriter(1.txt」), true);
pw2.println(「hello」);
pw2.close();

九. 物件序列化流與反序列化流

(一) 物件序列化流

1. 物件序列化

       將物件以一個位元組序列的方式表示,該序列包含:物件的型別,物件的數據,物件中儲存的屬性。並將該序列儲存到磁碟中或在網路中傳輸。

2. 物件序列化流:ObjectOutputStream

       將數據物件寫入OutputStream流中,儲存在磁碟中或者網路傳輸。

3. 構造方法


方法名 說明
ObjectOutputStream(OutputStream out) 建立一個寫入指定的OutputStream的 ObjectOutputStream

4. 序列化物件的方法


方法名 說明
void writeObject(Object obj) 將指定的物件寫入ObjectOutputStream

5. 注意事項

       (1) 物件要實現序列化,所屬的類需實現Serializable介面

       (2) Serializable介面是標記介面,不需重寫方法。

6. 範例


package File使用;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class 物件序列化 {
    public static void main(String[] args) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Student\\1.txt"));

        Student s = new Student("dd", 99, 99, 99);

        oos.writeObject(s);

        oos.close();
    }
}

(二) 物件反序列化

1. 物件反序列化

       將物件被序列化的序列逆向生成原始的物件。

2. 物件反序列化流

       ObjectInputStream

3. 構造方法


方法名 說明
ObjectInputStream(InputStream in) 建立從指定的InputStream讀取的ObjectInputStream

4. 反序列化物件的方法


方法名 說明
Object readObject() 從ObjectInputStream讀取一個物件

5. 範例


package File使用;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class 物件反序列化 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Student\\1.txt"));
        Object obj = ois.readObject();
        Student s = (Student)obj;
        System.out.println(s.getName() + ":" + s.getSum());

        ois.close();
    }
}

(三) 序列化物件中的問題

1. serialVersionUID

       序列化執行時與每個可序列化的類關聯一個版本號,它在反序列化時使用,以驗證序列化物件的發送者和接受者是否載入了與序列化相容的物件的類。

       一個可序列化的類可以顯示宣告自己的serialVersionUID,該欄位爲static,final,long型別的,建議所有可序列化的類都要顯示宣告serialVersionUID。

private static final long serialVersionUID;

2. transient

       如果不想類中的某個成員變數被序列化,則將該成員宣告爲transient即可。


十. Properties集合

(一) 概述

       Properties是一個Map體系的集合類,可以用於將數據儲存到流中或從流中載入數據,用鍵值對儲存字串。

       注意,構造方法不是泛型方法,不需要傳入型別,而是直接建立新物件。

Properties prop = new Properties();

(二) 特有方法


方法名 說明
Object setProperty(String key, String value) 設定集合的鍵和值,都是String型別,底層呼叫 Hashtable方法 put
String getProperty(String key) 使用此屬性列表中指定的鍵搜尋屬性
Set stringPropertyNames() 從該屬性列表中返回一個不可修改的鍵集,其中鍵及其對應的值是字串

(三) Properties和IO流結合的方法


方法名 說明
void load(InputStream inStream) 從輸入位元組流讀取屬性列表(鍵和元素對)
void load(Reader reader) 從輸入字元流讀取屬性列表(鍵和元素對)
void store(OutputStream out, String comments) 將此屬性列表(鍵和元素對)寫入此 Properties表中,以適合於使用load(InputStream)方法的格式寫入輸出位元組流
void store(Writer writer, String comments) 將此屬性列表(鍵和元素對)寫入此 Properties表中,以適合使用load(Reader)方法的格式寫入輸出字元流

十一. IO流的總結

(一) 位元組流

       一般採用的是位元組緩衝流一次讀寫一個位元組陣列的方式
在这里插入图片描述

(二) 字元流


       字元流都是用來操作文字數據,一般用字元緩衝流的特有方法。
在这里插入图片描述