位元組流與和字元流的使用非常相似,兩者除了操作代碼上的不同之外,是否還有其他的不同呢?實際上位元組流在操作時本身不會用到緩衝區(記憶體),是文件本身直接操作的,而字元流在操作時使用了緩衝區,通過緩衝區再操作文件,如圖12-6所示。下麵以兩個寫文件的操作為主進行比較,但是在操作時位元組流和字元流的操作完成之後 ...
位元組流與和字元流的使用非常相似,兩者除了操作代碼上的不同之外,是否還有其他的不同呢?
實際上位元組流在操作時本身不會用到緩衝區(記憶體),是文件本身直接操作的,而字元流在操作時使用了緩衝區,通過緩衝區再操作文件,如圖12-6所示。
下麵以兩個寫文件的操作為主進行比較,但是在操作時位元組流和字元流的操作完成之後都不關閉輸出流。
範例:使用位元組流不關閉執行
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(); // 此時沒有關閉 } }
程式運行結果:
此時沒有關閉位元組流操作,但是文件中也依然存在了輸出的內容,證明位元組流是直接操作文件本身的。而下麵繼續使用字元流完成,再觀察效果。
範例:使用字元流不關閉執行
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(); // 此時沒有關閉 } }
程式運行結果:
程式運行後會發現文件中沒有任何內容,這是因為字元流操作時使用了緩衝區,而 在關閉字元流時會強制性地將緩衝區中的內容進行輸出,但是如果程式沒有關閉,則緩衝區中的內容是無法輸出的,所以得出結論:字元流使用了緩衝區,而位元組流沒有使用緩衝區。
提問:什麼叫緩衝區?
在很多地方都碰到緩衝區這個名詞,那麼到底什麼是緩衝區?又有什麼作用呢?
回答:緩衝區可以簡單地理解為一段記憶體區域。
可以簡單地把緩衝區理解為一段特殊的記憶體。
某些情況下,如果一個程式頻繁地操作一個資源(如文件或資料庫),則性能會很低,此時為了提升性能,就可以將一部分數據暫時讀入到記憶體的一塊區域之中,以後直接從此區域中讀取數據即可,因為讀取記憶體速度會比較快,這樣可以提升程式的性能。
在字元流的操作中,所有的字元都是在記憶體中形成的,在輸出前會將所有的內容暫時保存在記憶體之中,所以使用了緩衝區暫存數據。
如果想在不關閉時也可以將字元流的內容全部輸出,則可以使用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.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等