C++二进制文件读写操作
二进制文件的读写稍微麻烦一些,对二进制文件的读写同样需要打开文件和关闭文件,打开和关闭方式与文本文件相同,只不过需要在打开方式上加上 ios::binary 以指明以二进制方式进行读写。
对于文本文件而言,我们只能用 ofstream 类定义对象用于输出到文件,用 ifstream 类定义对象用于从文件中输入,而对于二进制文件而言,除了可以这么做以外,我们还可以用 fstream 类定义对象既能用于从文件输入,又能输出到文件中。
针对二进制文件的读写,输入输出类中定义了专门的函数 read() 和 write(),这两个都是类的成员函数,它们的函数原型为:
有了这两个用于读写二进制文件的函数,我们通过示例来看一下如何使用这两个函数:
我们来细看一下程序中主函数的执行过程:
1) 一开始定义了一个数组 A[3][10] 并赋了初值,之后又定义了另一个数组 B[3][10],用于存放从文件中读入的数据,程序先将 A[3][10] 数组中的数据打印出来。
2) 定义一个 ofstream 类的对象,以二进制方式打开文件,这种文件打开方式和文本文件打开方式是一样的,检测文件是否打开方法也是一样的。
3) 文件正常打开之后,我们开始将 A[3][10] 数组中的数据以二进制的形式输出到文件中。通过 ofstream 类的对象调用 write() 函数,因为 write() 函数的第一个参数为 char* 指针,因此需要进行一次强制类型转换,第二个参数给出了数组 A[3][10] 在内存中所占空间大小。因为数组在内存中是连续存储的,因此我们可以只用这么一个语句,就将所有的数组内容以二进制的方式写入到文本中。之后输出数据操作结束,关闭文件。
4) 紧接着,程序开始从文件中读入数据,打开文件也是和打开文本文件是一样的,只是在打开方式处添加了 ios::binary 以指明以二进制方式打开文件。同样的,我们也可以利用一个语句就将文件中的所有数据都读入到 B[3][10] 数组中。之后我们将 B[3][10] 数组中的数据打印出来。
当然,在程序设计过程中,我们有时候并不会像本例这样的,每次都将一堆数据全部存入文件或者将一堆数据全部读入到内存,很可能只需要获取某个指定位置的数据而已,此时如果需要将数据全部读入再找到数据的存储位置,效率实在太低。为此,系统提供了一些操作文件读写指针位置的成员函数,我们可以使用这些函数,将文件读写指针移动到指定位置并操作其中的数据,具体函数见下表。
表中所列函数以“g”(get 的首字母)结尾的函数都是用于输入的函数,而以“p”(put 的首字母)结尾的函数都是用于输出的函数。函数中有提到参照位置,在系统中定义了三种参照位置:
在本节的示例程序中,我们使用 seekg() 将文件读写指针以文件开头为标准移动 20 个 int 型数据,此时指针指向的是第三行第一列的数据,然后我们用 read() 函数将数据读入到 temp() 中,输出 temp() 结果确实是第三行第一列中的数据 9。
声明:《C++系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。
对于文本文件而言,我们只能用 ofstream 类定义对象用于输出到文件,用 ifstream 类定义对象用于从文件中输入,而对于二进制文件而言,除了可以这么做以外,我们还可以用 fstream 类定义对象既能用于从文件输入,又能输出到文件中。
针对二进制文件的读写,输入输出类中定义了专门的函数 read() 和 write(),这两个都是类的成员函数,它们的函数原型为:
istream & read ( char * buffer, int size ); ostream & write ( const char * buffer, int size );buffer 是指向内存中的一段存储空间,size 是存储空间的大小,也即需要读写的内容的字节数。
有了这两个用于读写二进制文件的函数,我们通过示例来看一下如何使用这两个函数:
#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 文件中,之后再从这个文件中读出其中的数据赋值给另外一个数组。
我们来细看一下程序中主函数的执行过程:
1) 一开始定义了一个数组 A[3][10] 并赋了初值,之后又定义了另一个数组 B[3][10],用于存放从文件中读入的数据,程序先将 A[3][10] 数组中的数据打印出来。
2) 定义一个 ofstream 类的对象,以二进制方式打开文件,这种文件打开方式和文本文件打开方式是一样的,检测文件是否打开方法也是一样的。
3) 文件正常打开之后,我们开始将 A[3][10] 数组中的数据以二进制的形式输出到文件中。通过 ofstream 类的对象调用 write() 函数,因为 write() 函数的第一个参数为 char* 指针,因此需要进行一次强制类型转换,第二个参数给出了数组 A[3][10] 在内存中所占空间大小。因为数组在内存中是连续存储的,因此我们可以只用这么一个语句,就将所有的数组内容以二进制的方式写入到文本中。之后输出数据操作结束,关闭文件。
当然,如果我们想一个一个数据的输出到文件也不是不可以的,注释掉的那个语句就是一个一个元素输出的。
4) 紧接着,程序开始从文件中读入数据,打开文件也是和打开文本文件是一样的,只是在打开方式处添加了 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:文件结尾。
在本节的示例程序中,我们使用 seekg() 将文件读写指针以文件开头为标准移动 20 个 int 型数据,此时指针指向的是第三行第一列的数据,然后我们用 read() 函数将数据读入到 temp() 中,输出 temp() 结果确实是第三行第一列中的数据 9。
声明:《C++系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。