[Java筆記]day26

臨潼言承旭發表於2020-11-24

day26

IO

  1. IO是一個相對的概念,我們是站在**程式(記憶體)**的角度來區分InputOutput
  2. 流的分類
    在這裡插入圖片描述

在這裡插入圖片描述

  1. IO流的體系
    在這裡插入圖片描述

FileReader/FileWriter

  1. FileReader:將硬碟中的資料讀入記憶體
  • 使用步驟

    • 例項化File類物件,指明要操作的檔案
    • 提供具體的流,這裡是FileReader
    • 資料讀入,呼叫read()
    • 呼叫close()手動關閉流
  • read()過載說明

原型說明注意
int read()讀取單個字元,返回作為整數讀取的字元,如果已到達檔案的末尾,則返回-1返回值是int,注意型別轉換
int read(char[] cbuf)將字元讀入陣列。如果已到達流的末尾,則返回-1。否則返回本次讀取的字元數注意輸出
  • 舉例
@Test
public void testFileReader1() {
    FileReader fileReader = null;
    try {
        // 1. 例項化File物件,指明要操作的檔案
        File file = new File("hello.txt");
        fileReader = new FileReader(file);
        int data = 0;  // 儲存資料
        while ((data = fileReader.read()) != -1) { // 讀到檔案末尾返回-1
            System.out.print((char) data);  // 注意型別轉換
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (fileReader != null) {  // 防止空指標
                fileReader.close();    // 手動關閉流
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

@Test
public void testFileReader2() {
    FileReader fileReader = null;
    try {
        fileReader = new FileReader(new File("hello.txt"));
        char[] buffer = new char[5];
        int len = 0;  // 記錄讀入字元的長度
        while ((len = fileReader.read(buffer)) != -1 ) {
            String s = new String(buffer, 0, len);  // char[] --> String
            System.out.print(s);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (fileReader != null) {
            try {
                fileReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 說明:

    • 為了保證流資源一定可以執行關閉操作,需要使用try-catch-finally處理
    • 讀入的檔案一定要存在,否則會報FileNotFoundException
  1. FileWriter:將記憶體中的資料寫出到硬碟中
  • 使用步驟

    • 建立File物件,指明寫出的檔案
    • 建立輸出流物件
    • 資料的寫出操作
    • 關閉流
  • Writer方法說明

原型說明
void write(int c)寫入單個字元
void write(char[] cbuf)寫入字元陣列
void write(char[] cbuf, int off, int len)寫入字元陣列的某一部分。從off開始,寫入len個字元
void write(String str)寫入字串
void write(String str, int off, int len)寫入字串的某一部分
void flush()重新整理該流的緩衝,則立即將它們寫入預期目標
  • 使用舉例
@Test
public void testFileWriter() {
    FileWriter writer = null;
    try {
        // 建立File物件
        File file = new File("hello1.txt");
        writer = new FileWriter(file, true);  // 追加
        writer.write("Hello World\n");   // 寫入
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (writer != null) {
            try {
                writer.close(); // 關閉流
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 說明:
    • File可以不存在,不會報異常
    • 如果File不存在,在輸出過程中會自動建立此檔案
    • 如果File存在,在可以在構造器中顯式地設定append屬性,當appendtrue時,多次輸出會在原有檔案後追加;否則會覆蓋原檔案

FileInputStream/FileOutputSteam

  1. 適用情形
  • 對於文字檔案,使用字元流處理,例如:.txt.java.cpp
  • 對於非文字檔案,使用位元組流處理,例如:.doc.jpg.mp3.avi
  1. 舉例

FileInputStream/FileOutputStram的方法、注意事項與FileReader/FileWriter基本相同,這裡以複製檔案的例項演示使用

 /**
  * 複製檔案
  * @param srcPath 原始檔路徑
  * @param destPath 目標路徑
  */
public void copyFile(String srcPath, String destPath) {
    FileInputStream fis = null;
    FileOutputStream fos = null;
    try {
        File src = new File(srcPath);
        File dest = new File(destPath);

        fis = new FileInputStream(src);
        fos = new FileOutputStream(dest);

        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len = fis.read(buffer)) != -1) {
            fos.write(buffer, 0, len);
        }

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (fos != null) {
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (fis != null) {
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

對於檔案複製的操作,可以用位元組流複製文字檔案,因為不涉及編碼和解碼,只是單純複製

緩衝流

  1. 對應關係
抽象基類節點流處理流
InputStreamFileInputStreamBufferedInputStream
OutputStreamFileOutputStreamBufferedOutputStream
ReaderFileReaderBufferedFileWriter
WriterFileWriterBufferedWriter
  1. 作用:提高流的讀取、寫入速度,提高效率

內部提供了一個預設大小為DEFAULT_BUFFER_SIZE = 8192緩衝區

  1. 使用步驟
  • 建立File物件,指明具體檔案
  • 建立流物件
    • 建立節點流物件
    • 建立處理流物件
  • 對檔案內資料的操作
  • 關閉流
    • 關閉處理流物件
    • 關閉節點流物件

說明:

  1. 建立時,先建立內層的節點流,後建立處理流
  2. 關閉時,先關閉外層的處理流,後關閉節點流
  3. 在關閉外層處理流時,內層流也會關閉,所以關閉時只需要關閉外層處理流即可
  1. 例項

處理流的使用方法基本與節點流一致,但BufferedWriter中增加了按行讀取的方法,因此這裡以BufferedReader/BufferWriter為例,說明處理流的使用,BufferedInputStream/BufferedOutputStream使用方法類似

@Test
public void testBufferedReaderWrite() {
    BufferedReader br = null;
    BufferedWriter bw = null;
    try {
        // 造流
        br = new BufferedReader(new FileReader(new File("hello.txt")));
        bw = new BufferedWriter(new FileWriter(new File("hi.txt")));
        // 運算元據
        String line = null;
        while ((line = br.readLine()) != null) {
            bw.write(line);  // 不包含換行符
            bw.newLine();  // 手動換行
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        // 關閉流
        if (bw != null) {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (br != null) {
            try {
                bw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

轉換流

  1. 轉換流:屬於字元流
  • InputStreamReader:將一個位元組的輸入流轉換為字元的輸入流
  • OutputStreamWriter:將一個字元的輸出流轉換為位元組輸出流
  1. 作用:提供位元組流和字元流之間的轉換

解碼:位元組(陣列) --> 字元(陣列、串)
編碼:字元(陣列、串) --> 位元組(陣列)

  1. 綜合應用例項:轉換字元編碼

相關文章