參考:http://www.weixueyuan.net/view/6413.html
總結:
二進制文件的讀寫稍微麻煩一些,對二進制文件的讀寫同樣需要打開文件和關閉文件,打開和關閉方式與文本文件相同,只不過需要在打開方式上加上ios::binary以指明以二進制方式進行讀寫。
對於文本文件而言,我們只能用ofstream類定義對象用於輸出到文件,用ifstream類定義對象用於從文件中輸入,而對於二進制文件而言,除了可以這么做以外,我們還可以用fstream類定義對象既能用於從文件輸入,又能輸出到文件中。
針對二進制文件的讀寫,輸入輸出類中定義了專門的函數read和write,這兩個都是類的成員函數。
istream & read ( char * buffer, int size );
ostream & write ( const char * buffer, int size );
char指針buffer是指向內存中的一段存儲空間,size是存儲空間的大小,也即需要讀寫的內容的字節數。
有時我們只需要獲取某個指定位置的數據而已,此時如果需要將數據全部讀入再找到對應位置數據實在是效率太低。為此系統為我們提供了一些操作文件讀寫指針位置的成員函數,我們可以使用這些函數,將文件讀寫指針移動到指定位置並操作其中的數據。
| 函數 | 用途 |
|---|---|
| gcount ( ) | 返回最后一次輸入所讀入的字節數 |
| tellg ( ) | 返回輸入指針的當前位置 |
| seekg ( 文件中的位置 ) | 將輸入文件中指針移動到指定的位置 |
| seekg ( 位移量, 參照位置 ) | 以參照位置為標准移動指針 |
| tellp ( ) | 返回輸出文件指針當前位置 |
| seekp ( 文件中的位置 ) | 將輸出文件中指針移動到指定的位置 |
| seekp ( 位移量, 參照位置 ) | 以參照位置為為標准移動指針 |
---------------------------------------------------------
二進制文件的讀寫稍微麻煩一些,對二進制文件的讀寫同樣需要打開文件和關閉文件,打開和關閉方式與文本文件相同,只不過需要在打開方式上加上ios::binary以指明以二進制方式進行讀寫。
對於文本文件而言,我們只能用ofstream類定義對象用於輸出到文件,用ifstream類定義對象用於從文件中輸入,而對於二進制文件而言,除了可以這么做以外,我們還可以用fstream類定義對象既能用於從文件輸入,又能輸出到文件中。
針對二進制文件的讀寫,輸入輸出類中定義了專門的函數read和write,這兩個都是類的成員函數,它們的函數原型為:
istream & read ( char * buffer, int size ); ostream & write ( const char * buffer, int size );
char指針buffer是指向內存中的一段存儲空間,size是存儲空間的大小,也即需要讀寫的內容的字節數。有了這兩個用於讀寫二進制文件的函數,我們通過示例來看一下如何使用這兩個函數。
例1:
#include <iostream> #include <fstream> using namespace std; int main() { int A[ 3 ][ 10 ] = { { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }, { 1, 2, 3, 4, 7, 7, 7, 7, 7, 7 }, { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 } }; int B[ 3 ][ 10 ]; int i, j; for( i = 0; i < 3; i++ ) { for( j = 0 ; j < 10; j++ ) { cout << A[ i ][ j ] <<" "; } cout << endl; } cout << endl; //******************************************* ofstream output( "test.txt", ios::out | ios::binary ); if( ! output ) { cerr << "Open output file error!" << endl; exit( -1 ); } output.write ((char *) A, sizeof( A ) ); for( i = 0; i < 3; i++ ) { for( j = 0 ; j < 10; j++ ) { //output.write ( ( char * ) & A [ i ][ j ], sizeof( A [ i ][ j ] ) ); } } output.close(); //******************************************* ifstream input( "test.txt", ios::in | ios::binary ); if( ! input ) { cerr << "Open input file error!" << endl; exit( -1 ); } input.read( ( char * ) & B , sizeof( B ) ); for( i = 0; i < 3; i++ ) { for( j = 0 ; j < 10; j++ ) { //input.read ( ( char * ) & B[ i ][ j ], sizeof( B[ i ][ j ] )); } } for( i = 0; i < 3; i++ ) { for( j = 0 ; j < 10; j++ ) { cout << B[ i ][ j ] <<" "; } cout << endl; } //******************************************* int temp; input.seekg( 20 * sizeof( int ), ios::beg ); input.read( ( char * ) & temp, sizeof( int )); cout << temp << endl; input.close(); return 0; }
這個例子的主要功能就是先將一個二維數組以二進制的方式寫入到一個test.txt文件中,之后再從這個文件中讀出其中的數據賦值給另外一個數組。我們來細看一下這個函數的主函數,我們一開始定義了一個數組A[ 3 ][ 10 ],並賦了初值,之后又定義了另一個數組B[ 3 ][ 10 ],用於存放從文件中讀入的數據。程序先將A[ 3 ][ 10 ]數組中的數據打印出來。之后定義一個ofstream類的對象,以二進制方式打開文件,這種文件打開方式和文本文件打開方式是一樣的,檢測文件是否打開方法也是一樣的。文件正常打開之后,我們就開始將A[ 3 ][ 10 ]數組中的數據以二進制的形式輸出到文件中,此時我們通過ofstream類的對象調用write函數,因為write函數的第一個參數為char指針,因此需要進行一次強制類型轉換,第二個參數給出了數組A[ 3 ][ 10 ]在內存中所占空間大小。因為數組在內存中是連續存儲的,因此我們可以只用這么一個語句,就將所有的數組內容以二進制的方式寫入到文本中,當然如果我們想一個一個數據的輸出到文件也不是不可以的,注釋掉的那個語句就是一個一個元素輸出的。之后輸出數據操作結束,關閉文件。
接下來程序開始從文件中讀入數據,打開文件也是和打開文本文件是一樣的,只是在打開方式處添加了ios::binary以指明以二進制方式打開文件。同樣的,我們也可以利用一個語句就將文件中的所有數據都讀入到B[ 3 ][ 10 ]數組中。之后我們將B[ 3 ][ 10 ]數組中的數據打印出來。
當然,在程序設計過程中,我們有時候並不會像本例這樣的,每次都將一堆數據全部存入文件或者將一堆數據全部讀入到內存,很可能我們只需要獲取某個指定位置的數據而已,此時如果需要將數據全部讀入在找到對應位置數據實在是效率太低。為此系統為我們提供了一些操作文件讀寫指針位置的成員函數,我們可以使用這些函數,將文件讀寫指針移動到指定位置並操作其中的數據,具體函數見下表。
| 函數 | 用途 |
|---|---|
| gcount ( ) | 返回最后一次輸入所讀入的字節數 |
| tellg ( ) | 返回輸入指針的當前位置 |
| seekg ( 文件中的位置 ) | 將輸入文件中指針移動到指定的位置 |
| seekg ( 位移量, 參照位置 ) | 以參照位置為標准移動指針 |
| tellp ( ) | 返回輸出文件指針當前位置 |
| seekp ( 文件中的位置 ) | 將輸出文件中指針移動到指定的位置 |
| seekp ( 位移量, 參照位置 ) | 以參照位置為為標准移動指針 |
表中所列函數以“g”(get的首字母)結尾的函數都是用於輸入的函數,而以“p”(put的首字母)結尾的函數都是用於輸出的函數。函數中有提到參照位置,在系統中定義了三種參照位置:
- ios::beg 所打開文件的開頭,這是默認值
- ios::cur 文件讀寫指針當前的位置
- ios::end 文件結尾
在本節例1中程序主函數的最后我們使用seekg將文件讀寫指針以文件開頭為標准移動20個int型數據,此時指針指向的是第三行第一列的數據,然后我們用read函數將數據讀入到temp中,輸出temp結果確實是第三行第一列中的數據9。
