文本文件和二進制文件
我們一般將文件分為文本文件和二進制文件。文本文件就是可以通過文本編輯器打開和編輯的文件,如使用Windows中的記事本(NotePad)或UNIX中的vi可以處理的文件。非文本文件都是二進制文件,我們不能直接使用文本編輯器編輯他們,而是通過計算機程序來處理的。常見的二進制文件,比如:圖片,視頻,音頻以及可執行文件。
也就是說,文本文件由字符序列構成,而二進制文件由二進制位序列構成。
但是從本質上說,文件都是二進制文件。因為對於計算機來說,它只能夠識別二進制的文件。我們所說的文本文件,其實本質也是二進制文件,只是通過編碼(encode)將二進制位轉換為了字符(編碼格式想必不用多說,常見的有ASCII,GBK,Unicode等),以便人類更好地閱讀。
因此我們說,文本I/O是建立在二進制I/O的基礎上的,在其之上提供了一層字符編碼/解碼的抽象。
二進制I/O不許要任何轉換。如果采用二進制I/O方式向文件中寫入一個數值,那么內存中存儲的值會原樣復制到文件中。
那么我們如何使用二進制I/O呢?在前邊的博客(C++ fstream和文件打開模式)提到過,要使用ios::binary打開文件。缺省條件下,文件是以文本文件打開的。
二進制文件的輸入和輸出
我們之前使用流操作符或者一些函數(put,get,getline)來讀寫文本文件。但是對於二進制文件,需要使用read和write函數,或者get、put、getline函數進行讀寫操作。
(為了方便下文用.dat文件表示二進制文件)
write函數
語法:
streamObject.write(const char* s, int size)
streamObject是流對象
s是一個字符數組
size是s的長度
下面看一個例子:
#include <iostream> #include <fstream> #include <string> using namespace std; int main() { ofstream binaryio("city.dat", ios::binary); string city = "北京"; binaryio.write(city.c_str(), sizeof(city)); binaryio.close(); cout << "二進制文件city.dat創建成功!" << endl; return 0; }
運行結果:


上面的例子中,寫入的是字符數據,但是很多情況下,我們要寫入非字符數據,如數字。那么我們可以使用reinterpret_cast來實現。此運算符可以將一個指針類型轉換為不相關的指針類型。它只是簡單地進行了指針值的二進制復制,並不改變指針所指向的數據。語法如下:
reinterpret_cast<datatype*>(address)
address是輸出數據的起始地址
datatype是希望轉換為的類型
在進行二進制I/O時,應轉換為char類型。
看下面的例子:
#include <iostream> #include <fstream> #include <string> using namespace std; int main() { ofstream binaryio("temp.dat", ios::binary); int value = 120; binaryio.write(reinterpret_cast<char*>(&value), sizeof(value)); binaryio.close(); cout << "二進制文件temp.dat創建成功!" << endl; return 0; }
運行結果:


read函數
語法:
streamObject.read(const char* address, int size)
size指最大字節數,實際讀取的字符數可以從成員函數gcount中獲取。
#include <iostream> #include <fstream> #include <string> using namespace std; int main() { ifstream binaryio("city.dat", ios::binary); char s[10]; binaryio.read(s,10); cout << "讀入的字節數為:" << binaryio.gcount() << endl; s[binaryio.gcount()] = '\0'; cout << s << endl; binaryio.close(); return 0; }
運行結果:

如果想讀入非字符數據,那么仍然使用reinterpret_cast
#include <iostream> #include <fstream> #include <string> using namespace std; int main() { ifstream binaryio("temp.dat", ios::binary); int value; binaryio.read(reinterpret_cast<char*>(&value),sizeof(value)); cout << "讀入的字節數為:" << binaryio.gcount() << endl; cout << value << endl; binaryio.close(); return 0; }
運行結果:

