Java中字節流和字符流的理解(超精簡!)

引言 

在完完全全的完成本學期的學習任務之後,終於可以有時間繼續更新Java相關的文章瞭。那麼今天我們要學習的是的Java中的IO流(I即為Input,O即為Output),也稱為輸入流,輸出流,其主要的作用是為瞭能夠對文件中的數據進行輸入和輸出(讀和寫),更加方便瞭今後我們在Java道路上的學習,好瞭,廢話不多說,我們開始今天的學習吧!

字節流和字符流 

在上圖中,橙色部分是抽象類,而藍色部分則是實現類

字節流 

字節流,顧名思義就是將數據細分為字節對文件進行讀和寫的操作, 主要分為字節輸入流和字節輸出流。

字節輸入流 

下面是字節輸入流中經常會用到的構造器和方法:

構造器 說明
public        FileInputStream(File file) 創建字節輸入流管道與源文件對象接通
public        FileInputStream(String pathname) 創建字節輸入流管道與源文件路徑接通
方法名稱 說明
public int read() 每次讀取一個字節返回,如果字節已經沒有可讀的返回-1
public int read(byte[ ] buffer) 每次讀取一個字節數組返回,如果字節已經沒有可讀的返回-1

接下來通過代碼更好的加深對這一部分知識點的理解吧!

File file = new File("File//data.txt");
        //第一種構造器,參數是File類
        InputStream inputStream = new FileInputStream(file);
        //第二種構造器,參數是文件的路徑,可以是相對也可以是絕對的路徑
        InputStream inputStream1 = new FileInputStream("File//data.txt");
        //通過字節讀取文件中的數據
        int len;
        while ((len=inputStream.read()) != -1){
            System.out.print((char) len);
        }
        System.out.println();
        //通過字節數組讀取文件中的數據
        byte [] buffer = new byte[3];
        while ((len=inputStream1.read(buffer))!=-1){
            String s = new String(buffer,0,len);
            System.out.print(s);
        }
//輸出結果:
//ab1abab
//ab1abab

現在我們看到的輸出結果和文件中的內容是一一對應的,那麼它就一定是沒有問題的瞭嗎?其實並不是,隻是還沒有遇到問題而已,首先我們應該瞭解到的是,在utf-8中,字母和數字都是一個字節,而中文是由三個字節組成的,那麼當我們的文件中出現漢字的時候,第一種方法就無法實現正常的讀取瞭,因為每次都讀取一個字節的原因會將漢字拆解,在輸出的時候形成亂碼的情況;而第二種則方法可以在特殊的情況下實現對漢字的輸出,必須滿足的條件是剛好中文的三個字節都在同一個字節數組中。

字節輸入流並不適合所有的文件數據,由此而引出瞭字符輸入流。

字節輸出流 

下面是字節輸出流常用到的方法:

方法 說明
public void write (int a) 寫一個字節出去
public void write (byte [ ]buffer) 寫一個字節數組出去
public void write (byte [ ]buffer,int off, int len) 將一個字節數組中的一部分寫出去
file.close() 流的關閉,不能再寫數據
file.flush() 流的更新,還可以繼續寫數據

 接下來通過代碼更好的加深對這一部分知識點的理解吧!

OutputStream outputStream = new FileOutputStream("File//data.txt",true);
//true表示可以對文件進行追加內容,若沒有true則會在關閉文件之後,進行寫文件的時候會對之前的內容進行覆蓋。
        outputStream.write('a');
        outputStream.write(13);
        outputStream.write('美');
        outputStream.flush();
        byte[] buffer = {'s','y','l','m',99};
        outputStream.write(buffer);
        outputStream.write(buffer,1,3);
        outputStream.close();

經過上面一系列操作以後,會將這些數據寫進data.txt文件之中,但是仍然會出現問題,有時無法將中文正常的寫進去,那麼它也不是一個適合所有文件的,由此而引出瞭字符輸出流。

字符流

字符流,顧名思義就是將數據細分為字符對文件進行讀和寫的操作, 主要分為字符輸入流和字符輸出流。 

字符輸入流 

 下面是字符輸入流中經常會用到的構造器和方法:

構造器 說明
public FileReader (File file) 創建字符輸入流管道與源文件對象接通
public FileReader(String pathname) 創建字符輸入流管道與源文件路徑接通
方法 說明
public int read() 每次讀取一個字符返回,如果字符已經沒有可讀的返回-1
public int read(char [ ]buffer) 每次讀取一個字符數組返回,返回讀取的字符個數,如果字符沒有可讀的返回-1

字符輸入流的構造器和方法大致上和字節輸入流的相同,不同的地方在於字符輸入流是以字符為單位的讀取,無論你是字母還是數字,都作為一個字符進行讀取,這樣便可以避免在讀取中文的時候出現亂碼的問題。

接下來通過一部分代碼來加深對它的理解吧!

File file = new File("File//data.txt");
        //第一種構造器,參數是File類
        FileReader fileReader = new FileReader(file);
        //第二種構造器,參數是文件的絕對路徑或者相對路徑
        FileReader fileReader1 = new FileReader("File//data.txt");
        //第一種方法,一個一個字符讀取
        int len;
        while ((len = fileReader.read())!=-1){
            System.out.print((char) len);
        }
        //第二種方法,以字符數組進行讀取
        char []buffer = new char[3];
        while ((len = fileReader1.read(buffer))!=-1){
            String s = new String(buffer,0,len);
            System.out.println(s);
        }
//輸出結果:
//110,119,120
//110
//,11
//9,1
//20

通過以字符為單位的讀寫,便可以避免在讀取中文的時候出現亂碼的問題瞭。

字符輸出流 

 下面是字符輸出流中經常會用到的構造器和方法:

構造器 說明
public FileWriter(File file) 創建字符輸出流管道與源文件對象接通
public FileWriter(File file,boolean append) 創建字符輸出流管道與源文件對象接通,可追加數據
public FileWriter(String filepath) 創建字符輸出流管道與源文件路徑接通
public FileWriter(String filepath,boolean append) 創建字符輸出流管道與源文件路徑接通,可追加
方法 說明
void writer(int c) 寫入一個字符
void writer (char [ ] buffer) 寫入一個字符數組
void writer (char[ ]buffer,int off,int len) 寫入字符數組的一部分
void writer(String str)         寫入一個字符串
void writer(String str,int off,int len) 寫入字符串的一部分
close和flush 輸出流的關閉和刷新

接下來就通過代碼來加深對它的理解吧!

FileWriter fileWriter = new FileWriter("File//data.txt");
        fileWriter.write('k');
        fileWriter.write('d');
        char []buffer = {'i','r','v','i','n','g'};
        fileWriter.write(buffer);
        fileWriter.flush();
        String s = "James";
        fileWriter.write(s);
        fileWriter.write(s,0,4);
        fileWriter.close();

字符輸出流的使用便可以很好地解決瞭中文不能正常寫入文件的問題瞭。 

附:字節流和字符流的區別

字節流操作的基本單元為字節;字符流操作的基本單元為Unicode碼元。

字節流默認不使用緩沖區;字符流使用緩沖區。

字節流在操作的時候本身是不會用到緩沖區的,是與文件本身直接操作的,所以字節流在操作文件時,即使不關閉資源,文件也能輸出;字符流在操作的時候是使用到緩沖區的。如果字符流不調用close或flush方法,則不會輸出任何內容。

字節流通常用於處理二進制數據,實際上它可以處理任意類型的數據,但它不支持直接寫入或讀取Unicode碼元;字符流通常處理文本數據,它支持寫入及讀取Unicode碼元。

字節流可用於任何類型的對象,包括二進制對象,而字符流隻能處理字符或者字符串; 字節流提供瞭處理任何類型的IO操作的功能,但它不能直接處理Unicode字符,而字符流就可以。

字節流和字符流的轉換

字節流是最基本的,所有的InputStream和OutputStream的子類都是,主要用在處理二進制數據,它是按字節來處理的,但實際中很多的數據是文本,又提出瞭字符流的概念,它是按虛擬機的encode來處理,也就是要進行字符集的轉化,這兩個之間通過 InputStreamReader,OutputStreamWriter來關聯,實際上是通過byte[]和String來關聯。在從字節流轉化為字符流時,實際上就是byte[]轉化為String時,而在字符流轉化為字節流時,實際上是String轉化為byte[]時。

字符流處理的單元為2個字節的Unicode字符,分別操作字符、字符數組或字符串,而字節流處理單元為1個字節,操作字節和字節數組。所以字符流是由Java虛擬機將字節轉化為2個字節的Unicode字符為單位的字符而成的,所以它對多國語言支持性比較好!如果是音頻文件、圖片、歌曲,就用字節流好點,如果是關系到中文(文本)的,用字符流好點。所有文件的儲存是都是字節(byte)的儲存,在磁盤上保留的並不是文件的字符而是先把字符編碼成字節,再儲存這些字節到磁盤。在讀取文件(特別是文本文件)時,也是一個字節一個字節地讀取以形成字節序列。

字節流可用於任何類型的對象,包括二進制對象,而字符流隻能處理字符或者字符串; 字節流提供瞭處理任何類型的IO操作的功能,但它不能直接處理Unicode字符,而字符流就可以。

字節流與字符流主要的區別是他們的的處理方式。

總結

到此這篇關於Java中字節流和字符流的文章就介紹到這瞭,更多相關Java字節流和字符流內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: