Java IO流詳解(四)----字符流Reader和Writer


前面一章介紹了字節流的使用,提到了字節流在處理 utf-8 編碼的中文可能會出現亂碼的情況(其他編碼的中文同樣會出現亂碼),所以Java針對這一情況提供了字符流。

但是字符流只能處理字符,不能用來處理 .jpg;.mp3;.mp4;.avi;.doc;.ppt等二進制文件,這些只能通過字節流來處理。所以對於純文本的文件,強烈推薦使用字符輸入輸出流。

字符流的本質其實就是基於字節流在讀取時去查了指定的碼表。

 

1、字符輸入流Reader

    Reader是所有字符輸入流的父類,定義了所有字符輸入流都具有的共同特征。其內部提供的方法如下:

image

上圖中重載的三個read()方法都是用來讀數據的。

  • int read():每次讀取一個字符,並把它轉換為 0~65535 的整數,然后返回讀取到的字符。讀到末尾返回-1。(為了提高 I/O 操作的效率,建議盡量使用下面兩種read()方法)
  • int read(char[] cbuf):將讀取到的多個字符存儲到 cbuf 中,然后返回讀取的字符,讀到末尾時返回-1。
  • int read(char[] cbuf,int off,int len):將讀取到的多個字符存儲進字符數組 cbuf,從索引 off 開始,長度為len字符,返回結果為讀取的字符數.

 

其中Reader的實現類FileReader是專門用於讀取文件中的數據,通過它將目標設備上的數據讀入到程序。

  FileReader讀入文件舉例(讀取的hello.txt文件內容是:你好,我是中國人!):

package com.thr;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

/**
 * @author Administrator
 * @date 2020-02-23
 * @desc 字符輸入流FileReader
 */
public class FileReaderTest {

    public static void main(String[] args)  {
        //定義輸入流
        FileReader fr =null;
        try {
            //1、創建文件對象
            File file = new File("D:\\IO\\hello.txt");
            //2、創建輸入流對象
            fr = new FileReader(file);

            //循環讀取,讀取到末尾返回-1
            int len ;//記錄每次讀取的字節個數
            while((len = fr.read())!=-1){
                System.out.print((char)len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //釋放資源
            try {
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
運行結果:
你好,我是中國人!

 

2、字符輸出流Writer

   Writer是所有字符輸出流的父類,定義了所有字符輸出流都具有的共同特征。其內部提供的方法如下:

image

上圖中重載的五個write()方法都是用來寫數據的。

  • void write(int c):把一個字符寫入到文件中。
  • void write(char[] cbuf):把cbuf字符數組寫入到文件中。
  • void write(char[] cbuf,int off,int len):把部分字符數組寫入到文件中,從 cbuf 數組的 off 索引開始,寫入len個字符。
  • void write(String str):把一個字符串寫入到文件中。
  • void write(String str,int off,int len):把部分字符串寫入到文件中,從 字符串的 off 索引開始,寫入len個字符。

 

其中Writer的實現類FileWriter是門用於讀出文件中的數據,通過它將數據從程序輸出到目標設備。

FileWriter輸出文件舉例:

package com.thr;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

/**
 * @author Administrator
 * @date 2020-02-23
 * @desc 字符輸出流FileWriter
 */
public class FileWriterTest {

    public static void main(String[] args)  {
        //定義輸出流
        FileWriter fw =null;
        try {
            //1、創建文件對象
            File file = new File("D:\\IO\\a.txt");
            //2、創建輸出流對象,保留原來的數據,在文件后面追加
            fw = new FileWriter(file,true);

            //write():寫出一個字符(utf-8編碼)
            fw.write(20200223);
            fw.write("\r\n");//回車換行

            //write(char[] buffer):把cbuf字符數組寫入到文件中。
            fw.write("我是中國人".toCharArray());
            fw.write("\r\n");

            //write(char[] cbuf,int off,int len):把部分字符數組寫入到文件中,從 cbuf 數組的 off 索引開始,寫入len個字符。
            fw.write("我是中國人".toCharArray(),1,4);
            fw.write("\r\n");

            //write(String str):把一個字符串寫入到文件中。
            fw.write("中國人");
            fw.write("\r\n");

            //write(String str,int off,int len):把部分字符串寫入到文件中,從 字符串的 off 索引開始,寫入len個字符。
            fw.write("你好,我是中國人\n",3,6);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //釋放資源
            try {
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

注意:如果字符輸出流不調用close()方法關閉資源,數據只是保存到緩沖區,並不會保存到文件(這一點與FileOutputStream不同,即使它不調用close()方法依然會寫入到文件中)。

這里就得介紹一下flush()這個方法。

flush()和close()方法的區別:

flush():將流中的緩沖區緩沖的數據刷新到目的地中,刷新后,流還可以繼續使用。

close():關閉資源,但在關閉前會將緩沖區中的數據先刷新到目的地,否則丟失數據,然后在關閉流。流不可以使用。

而當我們親自去使用flush()方法的時候會產生一個疑問,就算我們在close()之前不加flush()方法也不會影響文件的寫出呀,那為什么還要用這個方法呢?先看一下下面的代碼吧:

package com.thr;

import java.io.FileWriter;
import java.io.IOException;

/**
 * @author Administrator
 * @date 2020-02-24
 * @desc flush方法的使用
 */
public class WriterFlushTest {

        public static void main(String[] args) {

            //定義輸出流
            FileWriter fw = null;

            //其實該步就是在明確數據要存放的目的地
            try {
                fw=new FileWriter("D:\\flush.txt");
                fw.write("");//調用write方法,將字符串寫入到流中(使用write其實並沒有將字符串直接寫入到指定文件,而是存放在流中)
                fw.flush();//這一步才是將上一步write的所寫的字符串沖刷到指定的文件(在指定的文件打開后有字符串存在了)

                fw.write("");
                fw.flush();

                fw.write("flush方法");
                fw.flush();

                fw.close();//close()是一定要做的(其實close方法中調用了flush方法)

                fw.write("CCC");//close后若再write,會提示IO異常Stream closed

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
}

       小聲BB:我認為flush()方法可有可無,它就是將緩沖區的數據強制寫入到文件中,因為在調用完write()方法后數據並沒有寫入到文件中,而是保存在流中,此時我們可以調用flush()方法,也可以在最后用close()方法來將數據寫入文件,因為在close()的時候,也會進行一次flush的,因此close之前其實可以不用專門做flush的。但是在某些情況下,數據量較大的時候,在寫的過程中,可以進行階段性的flush。(話說我也不知道這樣做會有什么好處……)

3、字符流拷貝文件

package com.thr;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * @author Administrator
 * @date 2020-02-23
 * @desc 拷貝文本文件
 */
public class FileReaderWriterTest {

    public static void main(String[] args)  {
        //定義輸入流
        FileReader fr =null;
        //定義輸出流
        FileWriter fw =null;
        try {
            //創建讀入文件對象
            File f1 = new File("D:\\IO\\hello.txt");
            //創建讀出文件對象
            File f2 = new File("C:\\a.txt");

            fr = new FileReader(f1);
            fw = new FileWriter(f2);

            //循環讀取,讀取到末尾返回-1
            char chars[] = new char[1024];
            int len ;//記錄每次讀取的字節個數
            while((len = fr.read(chars))!=-1){
                fw.write(chars,0,len);
            }
            System.out.println("拷貝成功...");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //釋放資源
            try {
                fr.close();
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM