開啟檔案的模式的差異

開啟一個Text檔案與開啟一個Binary檔案進行讀寫有何不同?

在GNU System與相容POSIX 的系統中,開啟Text檔與開啟Binary檔案進行讀寫是無異的,不過在某些系統中,寫入Text檔與Binary檔是有所差異的,相關的資料可以參考GNU C Library的第十二章 Input/Output on Streams。

以下是此問題在GNU C library中相關內容,只擷取部份內容。

12.17 Text and Binary Streams

The GNU system and other POSIX-compatible operating systems organize all files as uniform sequences of characters. However, some other systems make a distinction between files containing text and files containing binary data, and the input and output facilities of ISO C provide for this distinction. This section tells you how to write programs portable to such systems.

Since a binary stream is always more capable and more predictable than a text stream, you might wonder what purpose text streams serve. Why not simply always use binary streams? The answer is that on these operating systems, text and binary streams use different file formats, and the only way to read or write “an ordinary file of text” that can work with other text-oriented programs is through a text stream.
In the GNU library, and on all POSIX systems, there is no difference between text streams and binary streams. When you open a stream, you get the same kind of stream regardless of whether you ask for binary. This stream can handle any file content, and has none of the restrictions that text streams sometimes have.

實際遇到的問題:
 我曾遇到這樣的問題,是發生在Windows的平台上,我寫一個程式是剖析網頁擷取部份資訊並顯示,而我那要拿去剖析的網頁是手動寫的一段HTML,利用記事本(Notepad)存成了編碼UTF-8,而問題就這麼發生了!

程式幾乎沒辦法讀取文字檔,只讀取了幾個byte就結束了,起初我覺得是我的迴圈判斷結束了,但是我反覆檢查,還另外開檔寫了一個小程式確認了判斷是無誤,但是剖析程式依然只讀取了那幾個byte就結束。
 最後使出殺手鐧,將所有讀到的byte與其對應位置都列出來,終於發現檔案指標竟然擅自跳掉,讀了幾個byte就跑到檔案結尾去,接著當然就結束了讀取,然後持續的嘗試解決這到問題,並在Linux系統上進行測試,編譯、執行,結果完全無誤,使我不禁懷疑Windows系統出現bug,但是我無從這樣斷定它是有 bug 的,就去請教了強者同學,而他猜測是開檔的模式使這段程式發生了問題,而他也沒猜錯當我將模式變為binary,整隻程式就無誤的正常執行。

最後確認是記事本的BOM並搭配上Windows在實做讀取binary與text是不同的方式,造成我的程式執行錯誤,這也是我們在程式設計上必須要注意的,養成讀取文字檔就用text模式,可能會讀取二進位檔就是用binary模式。

BOM: Wondows記事本在儲存成Unicode或是UTF-8文件時,都會在整分文件最前面添加三個位元組,方便判斷系統模式(為Big-Endium還是Little-Endium)與檔案編碼類型,不過這就會造成程式錯誤與誤判,包括C/C++編譯器都可能無法進行編譯。更多的資訊在英文維基條目:BOM中可以得到。

留言