C++ 讀取BIN文件的一些問題

程序要求讀取一個ARM的BIN文件,需要獲取每一個字節,寫了一個函數測試一下:

文件:


由於不熟悉,弄出了很多問題。相關問題如下:

1 BIN文件

(大部分見https://www.cnblogs.com/pengwangguoyh/articles/3223072.html)

BIN文件不以ASCII碼存放數據,它將內存中數據存儲形式不加轉換地傳送到磁盤文件,因此它又稱爲內存數據的映像文件。文件中的信息不是字符數據,而是字節中的二進制形式的信息,因此它又稱爲字節文件。

文本工具打開一個文件,如記事本,首先讀取文件物理上對應的二進制比特流,再按用戶選擇的解碼方式來解釋這個流,再顯示解釋結果。如果記事本無論打開什麼文件都按某種特定編碼(如ASCII碼),就可能出現亂碼。

如上面的test.bin文件,用EmEditor直接打開,(其編碼:GB2312),會提示某些字符無法用指定的編碼進行轉換。想要像上面這張圖方便地查看16進制,就要選擇以二進制方式打開(16進制試圖),如果選擇ASCII視圖,也是亂碼。

不管你怎麼樣,存儲的都還是那個東西。我們看到的字符並不代表存儲的是一個字符。如01000000按ASCII碼解碼,則對應是A,記事本可以顯示A,但是也有可能只是一個4字節int數據的四分之一。不管是二進制文件,還是文本文件,都是一連串的0和1,但是打開方式不同,對於這些0和1的處理也就不同。如果按照文本方式打開,在打開的時候會進行translate,將每個字節轉換成ASCII碼,而以按照二進制方式打開的話,則不會進行任何的translate;二進制文件是按二進制的編碼方式來存放文件的。例如,數5678的存儲形式爲:00010110 00101110 只佔二個字節。二進制文件雖然也可在屏幕上顯示,但其內容無法讀懂。C系統在處理這些文件時,並不區分類型,都看成是字符流,按字節進行處理。輸入輸出字符流的開始和結束只由程序控制而不受物理符號(如回車符)的控制。因此也把這種文件稱作“流式文件”。

2 C++ 讀取

C++打開文件,以什麼模式打開不重要,既改變不了文件本身的內容,也改變不了C/C++中系統函數的工作方式,所以只要關心這個文件裏的數據內容本身是二進制格式還是文本格式,如果內容是文本格式的,就調用文本格式那一套函數,比如puts,gets,fscanf,fprintf,<<,>>等,如果內容是二進制格式的,你就調用二進制格式那一套函數,比如fread,fwrite,ifstream.read(),ofstream.write()等。 只要保持文件內容與處理函數相對應相一致。

這個問題暫時沒有遇到,因爲打開時都指明瞭:ios::binary,調用的也是read(),先記下來以防以後出錯。

C++讀取BIN文件,可以用ifstream的read()。

原型: read( char *buffer, streamsize number );

有的文章裏第一個參數是unsigned char* ,但是vs2015裏看到的是char *。

buffer即指向緩衝區指針,number即讀取字節數。


3 類型的轉換

在類型的轉換這上面繞了很久:

首先程序要求,我要用unsigned int類型存儲每個字節,假設是k,read文件的第一個參數是char *,也就是說讀取的一個字節的數據類型是char,假設用x存儲,然而x直接賦值給k會出現錯誤。

每個數對應的是E3 A0 00 A0,(小端模式),

E3即1110 0011,擴展32位的話 1111 1111 1110 0011(我們看到的,存儲的就是補碼)

正好就是4294967267.

如果x是unsigned char,賦值給k就不會出錯。

但是在read函數參數裏要進行類型轉換,即改成read((char*)&x, 1))

&x是(unsigned char *)強制指針類型轉換成(char *),都是8位,對x沒有區別,指針強制類型轉換僅是將這個地址單元裏存儲的內容按不同的類型進行變量解釋和讀取,但如果這兩個指針指向數據類型字節數不同,數據就發生變化了。(如x:E3 還是1110 0011(不管解釋成char 還是 unsigned char )但如果轉換成 int類型 就會擴展x了)。

如此修改過後,結果正確了,如果不注意細節,就會有一些很繞人的錯誤:







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章