1. 程式人生 > 其它 >字元流與位元組流的區別

字元流與位元組流的區別

字元流與位元組流的區別

(尊重勞動成果,轉載請註明出處:https://blog.csdn.net/cynhafa/article/details/6882061 )
位元組流與和字元流的使用非常相似,兩者除了操作程式碼上的不同之外,是否還有其他的不同呢?

實際上位元組流在操作時本身不會用到緩衝區(記憶體),是檔案本身直接操作的,而字元流在操作時使用了緩衝區,通過緩衝區再操作檔案,如下圖所示。

下面以兩個寫檔案的操作為主進行比較,但是在操作時位元組流和字元流的操作完成之後都不關閉輸出流。

範例:使用位元組流不關閉執行

package org.lxh.demo12.byteiodemo;    
import java.io.File;    
import java.io.FileOutputStream;    
import java.io.OutputStream;    
public class OutputStreamDemo05 {    
public static void main(String[] args) throws Exception {   // 異常丟擲,  不處理    
// 第1步:使用File類找到一個檔案    
     File f = new File("d:" + File.separator + "test.txt"); // 宣告File  物件    
// 第2步:通過子類例項化父類物件    
     OutputStream out = null;            
// 準備好一個輸出的物件    
     out = new FileOutputStream(f);      
// 通過物件多型性進行例項化    
// 第3步:進行寫操作    
     String str = "Hello World!!!";      
// 準備一個字串    
     byte b[] = str.getBytes();          
// 字串轉byte陣列    
     out.write(b);                      
// 將內容輸出    
 // 第4步:關閉輸出流    
    // out.close();                  
// 此時沒有關閉    
        }    
    } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

程式執行結果:

此時沒有關閉位元組流操作,但是檔案中也依然存在了輸出的內容,證明位元組流是直接操作檔案本身的。而下面繼續使用字元流完成,再觀察效果。

範例:使用字元流不關閉執行

package org.lxh.demo12.chariodemo;    
import java.io.File;    
import java.io.FileWriter;    
import java.io.Writer;    
public class WriterDemo03 {    
    public static void main(String[] args) throws Exception { // 異常丟擲,  不處理    
        // 第1步:使用File類找到一個檔案    
        File f = new File("d:" + File.separator + "test.txt");// 宣告File 物件    
        // 第2步:通過子類例項化父類物件    
        Writer out = null;                 
// 準備好一個輸出的物件    
        out = new FileWriter(f);            
// 通過物件多型性進行例項化    
        // 第3步:進行寫操作    
        String str = "Hello World!!!";      
// 準備一個字串    
        out.write(str);                    
// 將內容輸出    
        // 第4步:關閉輸出流    
        // out.close();                   
// 此時沒有關閉    
    }    
}   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

程式執行結果:

程式執行後會發現檔案中沒有任何內容,這是因為字元流操作時使用了緩衝區,而 在關閉字元流時會強制性地將緩衝區中的內容進行輸出,但是如果程式沒有關閉,則緩衝區中的內容是無法輸出的,所以得出結論:字元流使用了緩衝區,而位元組流沒有使用緩衝區。

提問:什麼叫緩衝區?

在很多地方都碰到緩衝區這個名詞,那麼到底什麼是緩衝區?又有什麼作用呢?

回答:緩衝區可以簡單地理解為一段記憶體區域。

可以簡單地把緩衝區理解為一段特殊的記憶體。

某些情況下,如果一個程式頻繁地操作一個資源(如檔案或資料庫),則效能會很低,此時為了提升效能,就可以將一部分資料暫時讀入到記憶體的一塊區域之中,以後直接從此區域中讀取資料即可,因為讀取記憶體速度會比較快,這樣可以提升程式的效能。

在字元流的操作中,所有的字元都是在記憶體中形成的,在輸出前會將所有的內容暫時儲存在記憶體之中,所以使用了緩衝區暫存資料。

如果想在不關閉時也可以將字元流的內容全部輸出,則可以使用Writer類中的flush()方法完成。

範例:強制性清空緩衝區

package org.lxh.demo12.chariodemo;    
import java.io.File;    
import java.io.FileWriter;    
import java.io.Writer;    
public class WriterDemo04 {    
    public static void main(String[] args) throws Exception { // 異常丟擲不處理    
        // 第1步:使用File類找到一個檔案    
        File f = new File("d:" + File.separator + "test.txt");// 宣告File    
物件    
        // 第2步:通過子類例項化父類物件    
        Writer out = null;                   
// 準備好一個輸出的物件    
        out = new FileWriter(f);             
// 通過物件多型性進行例項化    
        // 第3步:進行寫操作    
        String str = "Hello World!!!";      
// 準備一個字串    
        out.write(str);                    
// 將內容輸出    
        out.flush();                       
// 強制性清空緩衝區中的內容    
        // 第4步:關閉輸出流    
        // out.close();                
// 此時沒有關閉    
    }    
}   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

程式執行結果:

此時,檔案中已經存在了內容,更進一步證明內容是儲存在緩衝區的。這一點在讀者日後的開發中要特別引起注意。

提問:使用位元組流好還是字元流好?

學習完位元組流和字元流的基本操作後,已經大概地明白了操作流程的各個區別,那麼在開發中是使用位元組流好還是字元流好呢?

回答:使用位元組流更好。

在回答之前,先為讀者講解這樣的一個概念,所有的檔案在硬碟或在傳輸時都是以位元組的方式進行的,包括圖片等都是按位元組的方式儲存的,而字元是隻有在記憶體中才會形成,所以在開發中,位元組流使用較為廣泛。

位元組流與字元流主要的區別是他們的的處理方式

流分類:
1.Java的位元組流
InputStream是所有位元組輸入流的祖先,而OutputStream是所有位元組輸出流的祖先。
2.Java的字元流
Reader是所有讀取字串輸入流的祖先,而writer是所有輸出字串的祖先。
InputStream,OutputStream,Reader,writer都是抽象類。所以不能直接new

位元組流是最基本的,所有的InputStream和OutputStream的子類都是,主要用在處理二進位制資料,它是按位元組來處理的
但實際中很多的資料是文字,又提出了字元流的概念,它是按虛擬機器的encode來處理,也就是要進行字符集的轉化
這兩個之間通過 InputStreamReader,OutputStreamWriter來關聯,實際上是通過byte[]和String來關聯
在實際開發中出現的漢字問題實際上都是在字元流和位元組流之間轉化不統一而造成的

在從位元組流轉化為字元流時,實際上就是byte[]轉化為String時,
public String(byte bytes[], String charsetName)
有一個關鍵的引數字符集編碼,通常我們都省略了,那系統就用作業系統的lang
而在字元流轉化為位元組流時,實際上是String轉化為byte[]時,
byte[] String.getBytes(String charsetName)
也是一樣的道理

至於java.io中還出現了許多其他的流,按主要是為了提高效能和使用方便,如BufferedInputStream,PipedInputStream等。需注意,使用BufferedOutputStream輸出資料時如果沒有關閉流,資料也是不會輸出到檔案當中的,即並不是所有位元組流都不用到緩衝區,輸入緩衝位元組流BufferedInputStream和輸出緩衝位元組流BufferedOutputStream還是要用到緩衝區的。

補充:
字元流處理的單元為2個位元組的Unicode字元,分別操作字元、字元陣列或字串,而位元組流處理單元為1個位元組,操作位元組和位元組陣列。所以字元流是由Java虛擬機器將位元組轉化為2個位元組的Unicode字元為單位的字元而成的,所以它對多國語言支援性比較好!如果是音訊檔案、圖片、歌曲,就用位元組流好點,如果是關係到中文(文字)的,用字元流好點. 所有檔案的儲存是都是位元組(byte)的儲存,在磁碟上保留的並不是檔案的字元而是先把字元編碼成位元組,再儲存這些位元組到磁碟。在讀取檔案(特別是文字檔案)時,也是一個位元組一個位元組地讀取以形成位元組序列. 1.位元組流可用於任何型別的物件,包括二進位制物件,而字元流只能處理字元或者字串; 2. 位元組流提供了處理任何型別的IO操作的功能,但它不能直接處理Unicode字元,而字元流就可以。 位元組流與字元流主要的區別是他們的的處理方式