C++ 中的文件輸入 / 輸出 (5)

原作: Ilia Yordanov,? loobian@cpp-home.com

?

二進制文件的處理

?

雖然有規則格式( formatted )的文本(到目前為止我所討論的所有文件形式)非常有用,但有時候你需要用到無格式( unformatted )的文件——二進制文件。它們和你的可執行程序看起來一樣,而與使用 << >> 操作符創建的文件則大不相同。 get() 函數與 put() 函數則賦予你讀 / 寫無規則格式文件的能力:要讀取一個字節,你可以使用 get() 函數;要寫入一個字節,則使用 put() 函數。你應當回想起 get() ——我曾經使用過它。你可能會疑惑為什么當時我們使用它時,輸出到屏幕的文件內容看起來是文本格式的?嗯,我猜這是因為我此前使用了 << >> 操作符。

?

譯注:作者的所謂“規則格式文本( formatted text )”即我們平時所說的文本格式,而與之相對的“無格式文件( unformatted files )”即以存儲各類數據或可執行代碼的非文本格式文件。通常后者需要讀入內存,在二進制層次進行解析,而前者則可以直接由預定好的 << >> 操作符進行讀入 / 寫出(當然,對后者也可以通過恰當地重載 << >> 操作符實現同樣的功能,但這已經不是本系列的討論范圍了)。

?

get() 函數與都各帶一個參數:一個 char 型變量 (譯注:指 get() 函數) 或一個字符 (譯注:指 put() 函數,當然此字符也可以以 char 型變量提供)

假如你要讀 / 寫一整塊的數據,那么你可以使用 read() write() 函數。它們的原型如下:

?

istream &read(char *buf, streamsize num);

ostream &write(const char *buf, streamsize num);

?

對于 read() 函數, buf 應當是一個字符數組,由文件讀出的數據將被保存在這兒。對于 write() 函數, buf 是一個字符數組,它用以存放你要寫入文件的數據。對于這兩個函數, num 是一個數字,它指定你要從文件中讀取 / 寫入的字節數。

假如在讀取數據時,在你讀取“ num ”個字節之前就已經到達了文件的末尾,那么你可以通過調用 gcount() 函數來了解實際所讀出的字節數。此函數會返回最后一次進行的對無格式文件的讀入操作所實際讀取的字節數。

在給出示例代碼之前,我要補充的是,如果你要以二進制方式對文件進行讀 / 寫,那么你應當將 ios::binary 作為打開模式加入到文件打開的參數表中。

現在就讓我向你展示示例代碼,你會看到它是如何運作的。

?

示例 1 :使用 get( ) put( )

?

#include <fstream.h>

?

void main()

{

??? fstream File("test_file.txt",ios::out | ios::in | ios::binary);

?

??? char ch;

??? ch='o';

?

??? File.put(ch); // ch 的內容寫入文件

?

??? File.seekg(ios::beg); // 定位至文件首部

?

??? File.get(ch); // 讀出一個字符

?

??? cout << ch << endl; // 將其顯示在屏幕上

?

??? File.close();

}

?

示例 2 :使用 read( ) write( )

?

#include <fstream.h>

#include <string.h>

?

void main()

{

??? fstream File("test_file.txt",ios::out | ios::in | ios::binary);

?

??? char arr[13];

??? strcpy(arr,"Hello World!"); // Hello World! 存入數組

?

??? File.write(arr,5); // 將前 5 個字符—— "Hello" 寫入文件

?

??? File.seekg(ios::beg); // 定位至文件首部

?

??? static char read_array[10]; // 在此我將打算讀出些數據

?

??? File.read(read_array,3); // 讀出前三個字符—— "Hel"

?

??? cout << read_array << endl; // 將它們輸出 ??

?

??? File.close();

}