深入理解計算機系統(原書第二版) 文本文件和二進制文件

[size=large]網上關於文本文件與二進制文件的文章很多,但遺憾的是,這些文章講得都比較
散。下面我將結合所查到的資料,從多個角度談談文本文件與二進制文件。

一、文本文件與二進制文件的定義

大家都知道計算機的存儲在物理上是二進制的,所以文本文件與二進制文件的區
別並不是物理上的,而是邏輯上的。這兩者只是在編碼層次上有差異。

簡單來說,文本文件是基於字符編碼的文件,常見的編碼有ASCII編碼,UNICOD
E編碼等等。二進制文件是基於值編碼的文件,你可以根據具體應用,指定某個值是什麼
意思(這樣一個過程,可以看作是自定義編碼)。

從上面可以看出文本文件基本上是定長編碼的,基於字符嘛,每個字符在具體編
碼中是固定的,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_NU
LL_SOH"這四個控制符。

文本文件的存儲與其讀取基本上是個逆過程,不再累述。而二進制文件的存取顯然
與文本文件的存取差不多,只是編/解碼方式不同而已,也不再敘述。


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

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

很多書上還認爲,文本文件的可讀性要好些,存儲要花費轉換時間(讀寫要編譯碼)
,而二進制文件可讀性差,存儲不存在轉換時間(讀寫不要編解碼,直接寫值).這裏
的可讀性是從軟件使用者角度來說的,因爲我們用通用的記事本工具就幾乎可以瀏覽所
有文本文件,所以說文本文件可讀性好;而讀寫一個具體的二進制文件需要一個具體的
文件解碼器,所以說二進制文件可讀性差,比如讀BMP文件,必須用讀圖軟件.而這裏的
存儲轉換時間應該是從編程的角度來說的,因爲有些操作系統如windows需要對回車換行
符進行轉換(將''/n'',換成''/r/n'',所以文件讀寫時,操作系統需要一個一個字符的檢查
當前字符是不是''/n''或''/r/n'').這個在存儲轉換在Linux操作系統中並不需要,當然,當
在兩個不同的操作系統上共享文件時,這種存儲轉換又可能出來(如Linux系統和Window
s系統共享文本文件)。關於這個轉換怎樣進行,我將在下一篇文章《Linux文本文件與W
indows文本文件間的轉換》給出^_^

四、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和t
est2,然後再以文本方式

讀test1,以二進制方式讀test2.

#include<stdio.h>

int main()

{

FILE * fp_text,* fp_binary;

char write_buf[4]={''1'',''2'',''/n'',''3''};

char read_buf_text[6],read_buf_binary[6];

int read_count_text,read_count_binary;

//未檢測打開是否失敗

fp_text=fopen("test1","wt+");

fp_binary=fopen("test2","wb+");

fwrite(write_buf,4,1,fp_text);

fwrite(write_buf,4,1,fp_binary);

//fflush(fp_text);

//fflush(fp_binary);


fseek(fp_text,0L,SEEK_SET);//fseek附帶了fflush功能

fseek(fp_binary,0L,SEEK_SET);//

read_count_text=fread(read_buf_text,sizeof(char),5,fp_text);

read_count_binary=fread(read_buf_binary,sizeof(char),5,fp_binary);

//加''/0'',便於打印字符串

read_buf_text[read_count_text]=''/0'';

read_buf_binary[read_count_binary]=''/0'';

printf("In Text Mode:read_count=%d,string=%s/n",read_count_text,read_buf
_text);

printf("In Binary Mode:read_count=%d,string=%s/n",read_count_binary,read
_buf_binary);

fclose(fp_text);

fclose(fp_binary);

return 0;


}

2、該程序在VC6.0下編譯運行,顯示結果如下(追憶"//"及其右邊內容是我手動加的註釋
):

In Text Mode:read_count=4,string=12

3 //文本方式讀test1,讀到的字符與原先寫入test1的
字符一樣

In Binary Mode:read_count=4,string=12

3 //二進制方式讀test1,讀到的字符與原先寫入test1
的字符一樣

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

test1的內容:

12

3 //文本方式寫入的,有換行效果,參看下面的4

test2的內容

123 //二進制方式寫入的,無換行效果(記事本對"/r/n"之外的控制字符串無
顯示效果),參看下面的4

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

test1的內容

31 32 0D 0A 33//十六進制,5個字節,比寫入緩衝區多了一個字節,在''/n''(0AH)前
插了一個''/r''(0DH)

test2的內容

31 32 0A 33//十六進制,4個字節,與寫入緩衝區的值一致.


5、總結

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

6.補充說明

上述說明僅適用於windows,在linux中文本方式的讀寫與二進制方式的讀寫無差
別,不存在回車換行間的轉換.這樣當直接在windows和linux中共享文件時,將會出現
與回車換行相關的問題.下一篇文章《Linux文本文件與Windows文本文件間的轉換》將
給出Linux文本文件與Windows文本文件間轉換的C程序,敬請關注^_^


原文鏈接:[url]http://blog.csdn.net/hanchaoman/article/details/5888243[/url][/size]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章