天天看點

文本檔案與二進制檔案的編碼差别

網上關于文本檔案與二進制檔案的文章很多,但遺憾的是,這些文章講得都比較散。下面我将結合所查到的資料,從多個角度談談文本檔案與二進制檔案。

一、文本檔案與二進制檔案的定義

       大家都知道計算機的存儲在實體上是二進制的,是以文本檔案與二進制檔案的差別并不是實體上的,而是邏輯上的。這兩者隻是在編碼層次上有差異。

       簡單來說,文本檔案是基于字元編碼的檔案,常見的編碼有ascii編碼,unicode編碼等等。二進制檔案是基于值編碼的檔案,可以根據具體應用,指定某個值是什麼意思(這樣一個過程,可以看作是自定義編碼)。

       從上面可以看出文本檔案基本上是定長編碼的,基于字元,每個字元在具體編碼中是固定的,ascii碼是8個比特的編碼,unicode一般占16個比特。而二進制檔案可看成是變長編碼的,因為是值編碼,多少個比特代表一個值,完全由自定義決定。大家可能對bmp檔案比較熟悉,就拿它舉例子吧,其頭部是固定長度的檔案頭資訊,前2位元組用來記錄檔案為bmp格式,接下來的8個位元組用來記錄檔案長度,再接下來的4位元組用來記錄bmp檔案頭的長度。大家可以看出來,其編碼是基于值的(不定長的,2、4、8位元組長的值都有),是以bmp是二進制檔案。

二、文本檔案與二進制檔案的存取

       文本工具打開一個檔案的過程是怎樣的呢?拿記事本來說,它首先讀取檔案實體上所對應的二進制比特流(前面已經說了,存儲都是二進制的),然後按照所選擇的解碼方式來解釋這個流,然後将解釋結果顯示出來。一般來說,你選取的解碼方式會是ascii碼形式(ascii碼的一個字元是8個比特),接下來,它8個比特8個比特地來解釋這個檔案流。例如對于這麼一個檔案流"01000000_01000001_01000010_01000011"(下劃線”_”,是我為了增強可讀性,而手動添加的),第一個8比特''01000000''按ascii碼來解碼的話,所對應的字元是字元''a'',同理其它3個8比特可分别解碼為''bcd'',即這個檔案流可解釋成"abcd",然後記事本就将這個"abcd"顯示在螢幕上。

       事實上,世界上任何東西要與其他東西通信會話,都存在一個既定的協定,既定的編碼規範。人與人之間通過文字聯絡,如在漢語中,漢字“媽”代表生育你的那個人,這就是一種既定的編碼。但注意到這樣一種情況,漢字“媽”在日本文字裡有可能是你生育下的那個人,是以當一個中國人a與日本人b之間用“媽”這個字進行交流,出現誤解就很正常的。用記事本打開二進制檔案與上面的情況類似。記事本無論打開什麼檔案都按既定的字元編碼工作(如ascii碼),是以當他打開二進制檔案時,出現亂碼也是很必然的一件事情了,原因就在于解碼和譯碼不對應。例如檔案流''00000000_00000000_00000000_00000001''可能在二進制檔案中對應的是一個四位元組的整數int 1,但在記事本裡解釋就變成了"null_null_null_soh"這四個控制符。

       文本檔案的存儲與其讀取基本上是個逆過程,不再贅述。而二進制檔案的存取顯然與文本檔案的存取差不多,隻是編解碼方式不同而已,也不再叙述。

三、文本檔案與二進制檔案的優缺點

       因為文本檔案與二進制檔案的差別僅僅是編碼上不同,是以他們的優缺點就是編碼的優缺點,這個找本編碼的書來看看就比較清楚了。一般認為,文本檔案編碼基于字元定長,譯碼容易些;二進制檔案編碼是變長的,是以它靈活,存儲使用率要高些,譯碼難一些(不同的二進制檔案格式,有不同的譯碼方式)。關于空間使用率,想想看,二進制檔案甚至可以用一個比特來代表一個意思(位操作),而文本檔案任何一個意思至少是一個字元.

       很多書上還認為,文本檔案的可讀性要好些,存儲要花費轉換時間(讀寫要編譯碼), 而二進制檔案可讀性差,存儲不存在轉換時間(讀寫不要編解碼,直接寫值)。這裡的可讀性是從軟體使用者角度來說的,因為我們用通用的記事本工具就幾乎可以浏覽所有文本檔案,是以說文本檔案可讀性好;而讀寫一個具體的二進制檔案需要一個具體的檔案解碼器,是以說二進制檔案可讀性差,比如讀bmp檔案,必須用讀圖軟體。而這裡的存儲轉換時間應該是從程式設計的角度來說的,因為有些作業系統如windows需要對回車換行符進行轉換(将''/n'',換成''/r/n'',是以檔案讀寫時,作業系統需要一個一個字元的檢查目前字元是不是''/n''或''/r/n'').這個在存儲轉換在linux作業系統中并不需要,當然,當在兩個不同的作業系統上共享檔案時,這種存儲轉換又可能出來(如linux系統和windows系統共享文本檔案)。

四、c的文本讀寫和二進制讀寫

       應該說c的文本讀寫與二進制的讀寫是一個程式設計層次上的問題,與具體的作業系統有關,是以“用文本方式讀寫的檔案一定是文本檔案,用二進制讀寫的檔案一定是二進制檔案”這類觀點是錯誤的。下面的講述非明确指出作業系統類型,都暗指windows。c的文本方讀寫與二進制讀寫的差别僅僅展現在回車換行符的處理上。文本方式寫時,每遇到一個''/n''(0ah換行符),它将其換成''/r/n''(0d0ah,回車換行),然後再寫入檔案;當文本讀取時,它每遇到一個''/r/n''将其反變化為''/n'',然後送到讀緩沖區。正因為文本方式有''/n''--''/r/n''之間的轉換,其存在轉換耗時。二進制讀寫時,其不存在任何轉換,直接将寫緩沖區中資料寫入檔案。

總地來說,從程式設計的角度來說,C中文本或二進制讀寫都是緩沖區與檔案中二進制流的互動,隻是文本讀寫時有回車換行的轉換。是以當寫緩沖區中無換行符''/n''(0ah),文本寫與二進制寫的結果是一樣的,同理,當檔案中不存在''/r/n''(0dh0ah)時,文本讀與二進制讀的結果一樣。

下面給出一個小程式來證明前面的觀點。

1、編寫如下程式。該程式将字元串"12/n3"分别以文本方式和二進制方式寫入test1和test2,然後再以文本方式讀test1,以二進制方式讀test2。

2、該程式在vc6.0下編譯運作,顯示結果如下:

3、用記事本打開test1和test2,結果如下:

4、用vc6.0以binary方式(二進制方式)打開test1和test2,結果如下(用其他二進制讀寫軟體也可以) 

5、總結

    從4可以看出,文本方式寫時,存在''/n''->''/r/n''的轉換,而二進制方式無轉換。又從2和4可以推出,文本方式讀時存在''/r/n''->至''/n''的轉換,而二進制方式無轉換。有興趣的讀者可以嘗試以二進制方式讀test1或以文本方式讀test2,看會出現什麼效果。

6.補充說明

上述說明僅适用于windows,在unix/linux中文本方式的讀寫與二進制方式的讀寫無差别,不存在回車換行間的轉換。unix/linux并沒有區分這兩種檔案,他們對所有檔案一視同仁,将所有檔案都看成二進制檔案。标準i/o庫中 主要使用 fread/fwrite來讀寫二進制檔案,而對于文本檔案可以使用 fread/fwrite/fgetc/fputc fprintf等等。

轉載位址:http://blog.csdn.net/do2jiang/article/details/5863135

繼續閱讀