Java 字節流與字符流(1) 轉

Java 的 IO 系統是比較龐雜的,各種流特別多,其中有一種就是字符流。

在本系列前面的一些文章中,也曾涉及過字符流的話題,不過沒有詳細展開討論,這次準備具體綜合地談一談。
你可能聽過不少關於字節流與字符流對比的介紹,不過嚴格地說,我認爲把“字節流”和“字符流”去 對比這種說法不是特別妥當,爲什麼呢? 首先,這兩種流實際上 處在不同的層次,字節流是基礎,而字符流是構建在其上的: 對於不同層次上的事物,我認爲用“對比”這個詞是不太恰當的。 打個不太恰當的比方,比如說你跟隔壁老王同齡,然後你“拿你的兒子跟隔壁老王對比”,那隔壁老王可能就會質問你:“你什麼意思?拿你兒子跟我比?你咋不拿你爹跟我比呢?” 你可以“拿自己跟老王對比”,也可以“拿自己兒子跟老王兒子對比”,但你不能”拿你的兒子跟隔壁老王對比“,這就不恰當了,對吧?
要是一對比,發現兒子長得還挺像隔壁老王,那就尷尬了……
那麼這裏是想說明一個道理,就是不是一個輩分的,不應該去對比。
再打一個比方,就是好比你把“中國”去跟“美國的加利福尼亞州”去對比,通常意義都不大,我們一般都不會這樣去做。但在某些特殊情況下,比如想說明加州的經濟特別發達,可以拿加州的 GDP 跟整個中國的 GDP 對比,但這種對比只是爲了突出一方而不是爲了對比雙方。
那麼同理,處在不同層次的字節流與字符流,它們也不適合去“對比”。但是,可以研究“字節流”和“字符流”之間的關係,這是沒有問題的。那麼它們之間到底什麼關係呢?其實前面那個圖也揭示地很清楚了:
字節流是基礎,字符流是其上的抽象與封裝。
狹隘地講,比如僅僅從讀取或寫入文件方面去探討的話,那麼“字符流”是爲方便我們讀取或寫入“ 文本文件”而引入的抽象。也就是說:
字符流只對應文本文件; 而字節流則對應所有文件,自然也包括文本文件。
文本文件是開發活動中會大量接觸到的一類文件。所有語言的源代碼文件,像什麼 .java,.js 這些都是;還有很多比如 html,xml,css 之類的以及很多的配置文件也是文本文件。
簡單講,就是你可以用“記事本”打開查看的那類文件。
假如你一個文本文件要讀取,自然,最好的選擇是使用字符流。當然,你也可以選擇用字節流來讀取。(在後面,會給出一些具體的例子和代碼)
如果只要一下子就把整個文件讀取上來,那麼用字符流跟字節流的差別並不大。 但是,面臨某些具體的需求時,比方說,想一個一個“字符”的讀取上來,或者想一行一行地讀取時,用字符流就會很方便,而用字節流就會非常的麻煩。
另一方面,如果你要讀取的並不是一個文本文件,那就不能用字符流了。比如說,讀取一個圖片文件,或者是一個壓縮包,又或者是一個 word 文件或 pdf 文件。這些都不是“文本文件”,因此你不可以用字符流去讀取它們。
簡單講,就是你不可以用“記事本”打開去查看它們的那類文件。當然,如果你硬是要用記事本打開也不是不可以,畢竟在最底層,大家都不過是一堆 0 和 1 而已,但這種強行打開通常只會呈現爲一堆亂七八糟的東西。
非文本文件不可以用字符流去讀取,但它們都可以用字節流去讀取,因爲本質上來講,任何的文件都不過是字節的序列而已。 我看到有些介紹字節流與字符流的文章沒有特別去強調這一點,給人一種感覺,就好像這兩種流都能做任何事情,這顯然是錯誤的。 其實從名字上也不難想到,既然叫字符流,那肯定跟字符有關了。而對於圖片來說,構成元素是一個個“像素”,而不是什麼字符,所以自然不能用字符流去讀取圖片。初學者或許能意識到不能用字符流去讀圖片,但未必能清楚明白,其實還有很多的文件都不能用字符流去讀取的。 所以,前面強調兩者不能對比,強調兩者處在不同層次,在能力上,兩者也是有區別的,而所有的字符流最終它的底層其實還是字節流,字符流只是一種抽象。(甚至還不算是一個好的抽象,我們將在後面說明爲什麼) 對於構建一個字符流而言,其實有一個很重要的參數,卻經常被大家所忽略,就是字符集編碼。
爲什麼你可以忽略它呢?因爲有 缺省的存在。就好像你用記事本保存一個文本文件時,系統通常只提示你輸入文件名,而不會提示你選擇一個字符集編碼,但這並不是說編碼是可有可無的,當你沒有選擇編碼時,其實是系統悄悄地給你分配了一個缺省編碼。 某些時候,這帶來了方便,但也常常給我們帶來很多問題。
其實在前面的圖中,我把字符流寫成“gbk 字符流”,“utf-8 字符流”也是爲了凸顯這個編碼的存在,它不應該被忽略。 前面說,字符流構建在字節流基礎之上,其實更加確切的說法應該是:字符流構建在“字節流+字符集編碼”基礎之上,像這樣: 最後,字符流中所謂的“字符”其實跟我們認知還是有區別的,前面也說了,這裏的字符其實並不是一個很好的抽象。
這裏的“字符”嚴格說,只是 BMP 內的字符,對於 BMP 外的,情況就不同了。
在下一篇,再給出具體的示例。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章