問題始於社區的一個帖子,樓主的問題如下:
“在c語言中,對一個不知道大小的文件進行讀操作,我用fread()將文件的內容先放到一個緩存區,然后將緩存區中的內容打印出來,
緩存區中的內容和文件中的內容不一樣,好像是因為緩存區的空間比存儲文件內容所需要的空間大了,不知道應該怎么解決”
這個問題我之前也碰到過,翻了一些C語言文件操作方面的資料,發現對於換行的處理,其實是一個從打字機時代就有的歷史遺留問題:
“在計算機還沒有出現之前,有一種叫做電傳打字機(Teletype Model 33)的玩意,每秒鍾可以打10個字符。但是它有一個問題,就是打
完一行換行的時候,要用去0.2秒,正好可以打兩個字符。要是在這0.2秒里面,又有新的字符傳過來,那么這個字符將丟失。 於是,研制人員
想了個辦法解決這個問題,就是在每行后面加兩個表示結束的字符。一個叫做“回車”,告訴打字機把打印頭定位在左邊界;另一個叫做“換行”,
告訴打字機把紙向下移一行。 ”
在計算機出現之后,這種概念又被移植到了計算機操作系統上。當然,對於是否移植這一點也是有爭議的,Windows和Unix/Mac系統在這一點
上就分道揚鑣了。
下面首先討論在Windows平台下的情況。
Windows平台采用了歷史的概念,在文件中,換行被處理為“\r\n”兩個字符,也就是說,雖然用戶只敲了一次回車鍵,但其實系統
會認為收到了“\r\n”兩個字符,並同時存儲了這兩個字符。
因此,在Windows平台下,文件為了存儲一次換行會寫入兩個字符。當程序員試圖從文件中讀取文件內容時,C語言提供了兩種方式:文本方
式和二進制方式,這兩種方式又有什么區別呢?
在Windows平台下,采用文本方式打開一個文件時,會自動將一次換行,即“\r\n”兩個字符轉換成一個“\n”字符,即會去掉一個“\r”
字符,這種轉換的結果就是:實際讀取的數據長度會比文件的真實長度短,兩者之差等於文件中的換行次數。而當采用二進制方式打開
一個文件時,由於二進制方式打開的特點是有什么讀什么,因此,“\r\n”兩個字符會原封不動,均被讀取,因而實際讀取的數據長度與
原文件長度相同。
由於這種區別的存在,推薦大家在讀取文件時采用二進制方式,文件中是什么內容,讀取到的就是什么內容。
那么,在Unix平台下呢?
Unix/Mac平台並沒有采用Windows平台的方式,在Unix/Mac中,每一行的結尾只有一個換行符,即“\n”,因此,Unix/Mac平台下兩種讀取方式
是不會有區別的。
一個直接后果是,Unix/Mac系統下的文件在Windows里打開的話,所有文字會變成一行;而Windows里的文件在Unix/Mac下打開的話,
某些文本編輯器可能在每行的結尾會多出一個^M符號。