<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
通過前一節的學習,讀者瞭解了以文字形式讀寫檔案和以二進位制形式讀寫檔案的區別,並掌握了用過載的 >> 和 << 運運算元實現以文字形式讀寫檔案。在此基礎上,本節繼續講解如何以二進位制形式讀寫檔案。
不過介紹具體的實現方法前,先給讀者介紹一下相比以文字形式讀寫檔案,以二進位制形式讀寫檔案有哪些好處?
舉個例子,現在要做一個學籍管理程式,其中一個重要的工作就是記錄學生的學號、姓名、年齡等資訊。這意味著,我們需要用一個類來表示學生,如下所示:
class CStudent { char szName[20]; //假設學生姓名不超過19個字元,以 ' ' 結尾 char szId[l0]; //假設學號為9位,以 ' ' 結尾 int age; //年齡 };
前面章節中,我們學會了如何以文字形式讀寫檔案,如果使用此方式儲存學生的資訊,則最終的檔案中儲存的學生資訊可能是這個樣子:
Micheal Jackson 110923412 17
Tom Hanks 110923413 18
…
要知道,這種儲存學生資訊的方式不但浪費空間,而且後期不利於查詢指定學生的資訊(查詢效率低下),因為每個學生的資訊所佔用的位元組數不同。
這種情況下,以二進位制形式將學生資訊儲存到檔案中,是非常不錯的選擇,因為以此形式儲存學生資訊,可以直接把 CStudent 物件寫入檔案中,這意味著每個學生的資訊都只佔用 sizeof(CStudent) 個位元組。
值得一提的是,要實現以二進位制形式讀寫檔案,<< 和 >> 將不再適用,需要使用 C++ 標準庫專門提供的 read() 和 write() 成員方法。其中,read() 方法用於以二進位制形式從檔案中讀取資料;write() 方法用於以二進位制形式將資料寫入檔案。
ofstream 和 fstream 的 write() 成員方法實際上繼承自 ostream 類,其功能是將記憶體中 buffer 指向的 count 個位元組的內容寫入檔案,基本格式如下:
ostream & write(char* buffer, int count);
其中,buffer 用於指定要寫入檔案的二進位制資料的起始位置;count 用於指定寫入位元組的個數。
也就是說,該方法可以被 ostream 類的 cout 物件呼叫,常用於向螢幕上輸出字串。同時,它還可以被 ofstream 或者 fstream 物件呼叫,用於將指定個數的二進位制資料寫入檔案。
同時,該方法會返回一個作用於該函數的參照形式的物件。舉個例子,obj.write() 方法的返回值就是對 obj 物件的參照。
需要注意的一點是,write() 成員方法向檔案中寫入若干位元組,可是呼叫 write() 函數時並沒有指定這些位元組寫入檔案中的具體位置。事實上,write() 方法會從檔案寫指標指向的位置將二進位制資料寫入。所謂檔案寫指標,是是 ofstream 或 fstream 物件內部維護的一個變數,檔案剛開啟時,檔案寫指標指向的是檔案的開頭(如果以 ios::app 方式開啟,則指向檔案末尾),用 write() 方法寫入 n 個位元組,寫指標指向的位置就向後移動 n 個位元組。
下面的程式演示瞭如何將學生資訊以二進位制形式寫入檔案:
#include <iostream> #include <fstream> using namespace std; class CStudent { public: char szName[20]; int age; }; int main() { CStudent s; ofstream outFile("students.dat", ios::out | ios::binary); while (cin >> s.szName >> s.age) outFile.write((char*)&s, sizeof(s)); outFile.close(); return 0; }
輸入:
Tom 60↙
Jack 80↙
Jane 40↙
^Z↙
其中,↙表示輸出換行符,^Z 表示輸入Ctrl+Z組合鍵結束輸入。
執行程式後,會自動生成一個 students.dat 檔案,其內部存有 72 位元組的資料,如果用“記事本”開啟此檔案,可能看到如下亂碼:
Tom 燙燙燙燙燙燙燙燙< Jack 燙燙燙燙燙燙燙蘌 Jane 燙燙燙燙燙燙燙?
值得一提的是,程式中第 13 行指定檔案的開啟模式為 ios::out | ios::binary,即以二進位制寫模式開啟。在 Windows平臺中,以二進位制模式開啟檔案是非常有必要的,否則可能出錯。
另外,第 15 行將 s 物件寫入檔案。s 的地址就是要寫入檔案的記憶體緩衝區的地址,但是 &s 不是 char * 型別,因此要進行強制型別轉換;第 16 行,檔案使用完畢一定要關閉,否則程式結束後檔案的內容可能不完整。
ifstream 和 fstream 的 read() 方法實際上繼承自 istream 類,其功能正好和 write() 方法相反,即從檔案中讀取 count 個位元組的資料。該方法的語法格式如下:
istream & read(char* buffer, int count);
其中,buffer 用於指定讀取位元組的起始位置,count 指定讀取位元組的個數。同樣,該方法也會返回一個呼叫該方法的物件的參照。
和 write() 方法類似,read() 方法從檔案讀指標指向的位置開始讀取若干位元組。所謂檔案讀指標,可以理解為是 ifstream 或 fstream 物件內部維護的一個變數。檔案剛開啟時,檔案讀指標指向檔案的開頭(如果以 ios::app 方式開啟,則指向檔案末尾),用 read() 方法讀取 n 個位元組,讀指標指向的位置就向後移動 n 個位元組。因此,開啟一個檔案後連續呼叫 read() 方法,就能將整個檔案的內容讀取出來。
通過執行 write() 方法的範例程式,我們將 3 個學生的資訊儲存到了 students.dat 檔案中,下面程式演示瞭如何使用 read() 方法將它們讀取出來:
#include <iostream> #include <fstream> using namespace std; class CStudent { public: char szName[20]; int age; }; int main() { CStudent s; ifstream inFile("students.dat",ios::in|ios::binary); //二進位制讀方式開啟 if(!inFile) { cout << "error" <<endl; return 0; } while(inFile.read((char *)&s, sizeof(s))) { //一直讀到檔案結束 cout << s.szName << " " << s.age << endl; } inFile.close(); return 0; }
程式的輸出結果是:
Tom 60
Jack 80
Jane 40
注意,程式中第 18 行直接將 read() 方法作為 while 迴圈的判斷條件,這意味著,read() 方法會一直讀取到檔案的末尾,將所有位元組全部讀取完畢,while 迴圈才會終止。
另外,在使用 read() 方法的同時,如果想知道一共成功讀取了多少個位元組(讀到檔案尾時,未必能讀取 count 個位元組),可以在 read() 方法執行後立即呼叫檔案流物件的 gcount() 成員方法,其返回值就是最近一次 read() 方法成功讀取的位元組數。感興趣的讀者可自行嘗試,這裡不再做具體演示。
到此這篇關於C++用read()和write()讀寫二進位制檔案的文章就介紹到這了,更多相關C++ read()和write()讀寫二進位制檔案內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45