Error[8]: Undefined offset: 4, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

概述用文本方式存储信息不但浪费空间,而且不便于检索。例如,一个学籍管理程序需要记 我们先来说一下为什么要使用二进制文件,它比文本文件有哪些好处。

用文本方式存储信息不但浪费空间,而且不便于检索。例如,一个学籍管理程序需要记录所有学生的学号、姓名、年龄信息,并且能够按照姓名查找学生的信息。程序中可以用一个类来表示学生:
class CStudent{    char szname[20];  //假设学生姓名不超过19个字符,以 '
#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;}
' 结尾 char szID[l0]; //假设学号为9位,以 '
#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))) { //一直读到文件结束        int readedBytes = infile.gcount(); //看刚才读了多少字节        cout << s.szname << " " << s.age << endl;       }    infile.close();    return 0;}
' 结尾 int age; //年龄};
如果用文本文件存储学生的信息,文件可能是如下样子:
Micheal Jackson 110923412 17
Tom Hanks 110923413 18

这种存储方式不但浪费空间,而且查找效率低下。因为每个学生的信息所占用的字节数不同,所以即使文件中的学生信息是按姓名排好序的,要用程序根据名字进行查找仍然没有什么好办法,只能在文件中从头到尾搜索。

如果把全部的学生信息都读入内存并排序后再查找,当然速度会很快,但如果学生数巨大,则把所有学生信息都读人内存可能是不现实的。

可以用二进制的方式来存储学生信息,即把 CStudent 对象直接写入文件。在该文件中,每个学生的信息都占用 sizeof(CStudent) 个字节。对象写入文件后一般称作“记录”。本例中,每个学生都对应于一条记录。该学生记录文件可以按姓名排序,则使用折半查找的效率会很高。

读写二进制文件不能使用前面提到的类似于 cin、cout 从流中读写数据的方法。这时可以调用 ifstream 类和 fstream 类的 read 成员函数从文件中读取数据,调用 ofstream 和 fstream 的 write 成员函数向文件中写入数据。用 ostream::write 成员函数写文件ofstream 和 fstream 的 write 成员函数实际上继承自 ostream 类,原型如下:

ostream & write(char* buffer,int count);

该成员函数将内存中 buffer 所指向的 count 个字节的内容写入文件,返回值是对函数所作用的对象的引用,如 obj.write(...) 的返回值就是对 obj 的引用。

write 成员函数向文件中写入若干字节,可是调用 write 函数时并没有指定这若干字节要写入文件中的什么位置。那么,write 函数在执行过程中到底把这若干字节写到哪里呢?答案是从文件写指针指向的位置开始写入。

文件写指针是 ofstream 或 fstream 对象内部维护的一个变量。文件刚打开时,文件写指针指向文件的开头(如果以 ios::app 方式打开,则指向文件末尾),用 write 函数写入 n 个字节,写指针指向的位置就向后移动 n 个字节。

下面的程序从键盘输入几名学生的姓名和年龄(输入时,在单独的一行中按 Ctrl+Z 键再按回车键以结束输入。假设学生姓名中都没有空格),并以二进制文件形式存储,成为一个学生记录文件 students.dat。

例子,用二进制文件保存学生记录:
#include <iostream>#include <fstream>using namespace std;int main(int argc,char* argv[]){    if (argc != 3) {        cout << "file name missing!" << endl;        return 0;    }    ifstream infile(argv[l],ios::binary | ios::in);  //以二进制读模式打开文件    if (!infile) {        cout << "Source file open error." << endl;        return 0;    }    ofstream outfile(argv[2],ios::binary | ios::out);  //以二进制写模式打开文件    if (!outfile) {        cout << "New file open error." << endl;        infile.close();  //打开的文件一定要关闭        return 0;    }    char c;    while (infile.get(c))  //每次读取一个字符        outfile.put(c);  //每次写入一个字符    outfile.close();    infile.close();    return 0;}
输入:
Tom 60↙
Jack 80↙
Jane 40↙
^Z↙

则形成的 students.dat 为 72 字节,用“记事本”程序打开呈现乱码:

Tom烫烫烫烫烫烫烫烫 Jack烫烫烫烫烫烫烫? Jane烫烫烫烫烫烫烫?


第 13 行指定文件的打开模式是 ios::out|ios::binary,即以二进制写模式打开。在 windows平台中,用二进制模式打开是必要的,否则可能出错,原因会在《文件的文本打开方式和二进制打开方式的区别》一节中介绍。

第 15 行将 s 对象写入文件。s 的地址就是要写入文件的内存缓冲区的地址。但是 &s 不是 char * 类型,因此要进行强制类型转换。

第 16 行,文件使用完毕一定要关闭,否则程序结束后文件的内容可能不完整。用 istream::read 成员函数读文件ifstream 和 fstream 的 read 成员函数实际上继承自 istream 类,原型如下:

istream & read(char* buffer,int count);

该成员函数从文件中读取 count 个字节的内容,存放到 buffer 所指向的内存缓冲区中,返回值是对函数所作用的对象的引用。

如果想知道一共成功读取了多少个字节(读到文件尾时,未必能读取 count 个字节),可以在 read 函数执行后立即调用文件流对象的 gcount 成员函数,其返回值就是最近一次 read 函数执行时成功读取的字节数。gcount 是 istream 类的成员函数,原型如下:

int gcount();

read 成员函数从文件读指针指向的位置开始读取若干字节。文件读指针是 ifstream 或 fstream 对象内部维护的一个变量。文件刚打开时,文件读指针指向文件的开头(如果以ios::app 方式打开,则指向文件末尾),用 read 函数读取 n 个字节,读指针指向的位置就向后移动 n 个字节。因此,打开一个文件后连续调用 read 函数,就能将整个文件的内容读取出来。

下面的程序将前面创建的学生记录文件 students.dat 的内容读出并显示。[+++]程序的输出结果是:
Tom 60
Jack 80
Jane 40

第 18 行,判断文件是否已经读完的方法和 while(cin>>n) 类似,归根到底都是因为 istream 类重载了 bool 强制类型转换运算符。

第 19 行只是演示 gcount 函数的用法,删除该行对程序运行结果没有影响。

思考题:关于 students.dat 的两个程序中,如果 CStudent 类的 szname 的定义不是“char szname[20] ”而是“string szname”,是否可以?为什么?用文件流类的 put 和 get 成员函数读写文件可以用 ifstream 和 fstream 类的 get 成员函数(继承自 istream 类)从文件中一次读取一个字节,也可以用 ofstream 和 fstream 类的 put 成员函数(继承自 ostream 类) 向文件中一次写入一个字节。

例题:编写一个 mycopy 程序,实现文件复制的功能。用法是在“命令提示符”窗口输入:

mycopy 源文件名 目标文件名

就能将源文件复制到目标文件。例如:

mycopy src.dat dest.dat

即将 src.dat 复制到 dest.dat。如果 dest.dat 原本就存在,则原来的文件会被覆盖。

解题的基本思路是每次从源文件读取一个字节,然后写入目标文件。程序如下:[+++]文件存放于磁盘中,磁盘的访问速度远远低于内存。如果每次读一个字节或写一个字节都要访问磁盘,那么文件的读写速度就会慢得不可忍受。因此, *** 作系统在接收到读文件的请求时,哪怕只要读一个字节,也会把一片数据(通常至少是 512 个字节,因为磁盘的一个扇区是 512 B)都读取到一个 *** 作系统自行管理的内存缓冲区中,当要读下一个字节时,就不需要访问磁盘,直接从该缓冲区中读取就可以了。

*** 作系统在接收到写文件的请求时,也是先把要写入的数据在一个内存缓冲区中保存起来,等缓冲区满后,再将缓冲区的内容全部写入磁盘。关闭文件的 *** 作就能确保内存缓冲区中的数据被写入磁盘。

尽管如此,要连续读写文件时,像 mycopy 程序那样一个字节一个字节地读写,还是不如一次读写一片内存区域快。每次读写的字节数最好是 512 的整数倍。 总结

以上是内存溢出为你收集整理的C++二进制文件的读取和写入(精华版)全部内容,希望文章能够帮你解决C++二进制文件的读取和写入(精华版)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 5, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

概述用文本方式存储信息不但浪费空间,而且不便于检索。例如,一个学籍管理程序需要记 我们先来说一下为什么要使用二进制文件,它比文本文件有哪些好处。

用文本方式存储信息不但浪费空间,而且不便于检索。例如,一个学籍管理程序需要记录所有学生的学号、姓名、年龄信息,并且能够按照姓名查找学生的信息。程序中可以用一个类来表示学生:
class CStudent{    char szname[20];  //假设学生姓名不超过19个字符,以 '
#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;}
' 结尾 char szID[l0]; //假设学号为9位,以 '
#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))) { //一直读到文件结束        int readedBytes = infile.gcount(); //看刚才读了多少字节        cout << s.szname << " " << s.age << endl;       }    infile.close();    return 0;}
' 结尾 int age; //年龄};
如果用文本文件存储学生的信息,文件可能是如下样子:
Micheal Jackson 110923412 17
Tom Hanks 110923413 18

这种存储方式不但浪费空间,而且查找效率低下。因为每个学生的信息所占用的字节数不同,所以即使文件中的学生信息是按姓名排好序的,要用程序根据名字进行查找仍然没有什么好办法,只能在文件中从头到尾搜索。

如果把全部的学生信息都读入内存并排序后再查找,当然速度会很快,但如果学生数巨大,则把所有学生信息都读人内存可能是不现实的。

可以用二进制的方式来存储学生信息,即把 CStudent 对象直接写入文件。在该文件中,每个学生的信息都占用 sizeof(CStudent) 个字节。对象写入文件后一般称作“记录”。本例中,每个学生都对应于一条记录。该学生记录文件可以按姓名排序,则使用折半查找的效率会很高。

读写二进制文件不能使用前面提到的类似于 cin、cout 从流中读写数据的方法。这时可以调用 ifstream 类和 fstream 类的 read 成员函数从文件中读取数据,调用 ofstream 和 fstream 的 write 成员函数向文件中写入数据。用 ostream::write 成员函数写文件ofstream 和 fstream 的 write 成员函数实际上继承自 ostream 类,原型如下:

ostream & write(char* buffer,int count);

该成员函数将内存中 buffer 所指向的 count 个字节的内容写入文件,返回值是对函数所作用的对象的引用,如 obj.write(...) 的返回值就是对 obj 的引用。

write 成员函数向文件中写入若干字节,可是调用 write 函数时并没有指定这若干字节要写入文件中的什么位置。那么,write 函数在执行过程中到底把这若干字节写到哪里呢?答案是从文件写指针指向的位置开始写入。

文件写指针是 ofstream 或 fstream 对象内部维护的一个变量。文件刚打开时,文件写指针指向文件的开头(如果以 ios::app 方式打开,则指向文件末尾),用 write 函数写入 n 个字节,写指针指向的位置就向后移动 n 个字节。

下面的程序从键盘输入几名学生的姓名和年龄(输入时,在单独的一行中按 Ctrl+Z 键再按回车键以结束输入。假设学生姓名中都没有空格),并以二进制文件形式存储,成为一个学生记录文件 students.dat。

例子,用二进制文件保存学生记录:
#include <iostream>#include <fstream>using namespace std;int main(int argc,char* argv[]){    if (argc != 3) {        cout << "file name missing!" << endl;        return 0;    }    ifstream infile(argv[l],ios::binary | ios::in);  //以二进制读模式打开文件    if (!infile) {        cout << "Source file open error." << endl;        return 0;    }    ofstream outfile(argv[2],ios::binary | ios::out);  //以二进制写模式打开文件    if (!outfile) {        cout << "New file open error." << endl;        infile.close();  //打开的文件一定要关闭        return 0;    }    char c;    while (infile.get(c))  //每次读取一个字符        outfile.put(c);  //每次写入一个字符    outfile.close();    infile.close();    return 0;}
输入:
Tom 60↙
Jack 80↙
Jane 40↙
^Z↙

则形成的 students.dat 为 72 字节,用“记事本”程序打开呈现乱码:

Tom烫烫烫烫烫烫烫烫 Jack烫烫烫烫烫烫烫? Jane烫烫烫烫烫烫烫?


第 13 行指定文件的打开模式是 ios::out|ios::binary,即以二进制写模式打开。在 windows平台中,用二进制模式打开是必要的,否则可能出错,原因会在《文件的文本打开方式和二进制打开方式的区别》一节中介绍。

第 15 行将 s 对象写入文件。s 的地址就是要写入文件的内存缓冲区的地址。但是 &s 不是 char * 类型,因此要进行强制类型转换。

第 16 行,文件使用完毕一定要关闭,否则程序结束后文件的内容可能不完整。用 istream::read 成员函数读文件ifstream 和 fstream 的 read 成员函数实际上继承自 istream 类,原型如下:

istream & read(char* buffer,int count);

该成员函数从文件中读取 count 个字节的内容,存放到 buffer 所指向的内存缓冲区中,返回值是对函数所作用的对象的引用。

如果想知道一共成功读取了多少个字节(读到文件尾时,未必能读取 count 个字节),可以在 read 函数执行后立即调用文件流对象的 gcount 成员函数,其返回值就是最近一次 read 函数执行时成功读取的字节数。gcount 是 istream 类的成员函数,原型如下:

int gcount();

read 成员函数从文件读指针指向的位置开始读取若干字节。文件读指针是 ifstream 或 fstream 对象内部维护的一个变量。文件刚打开时,文件读指针指向文件的开头(如果以ios::app 方式打开,则指向文件末尾),用 read 函数读取 n 个字节,读指针指向的位置就向后移动 n 个字节。因此,打开一个文件后连续调用 read 函数,就能将整个文件的内容读取出来。

下面的程序将前面创建的学生记录文件 students.dat 的内容读出并显示。程序的输出结果是:
Tom 60
Jack 80
Jane 40

第 18 行,判断文件是否已经读完的方法和 while(cin>>n) 类似,归根到底都是因为 istream 类重载了 bool 强制类型转换运算符。

第 19 行只是演示 gcount 函数的用法,删除该行对程序运行结果没有影响。

思考题:关于 students.dat 的两个程序中,如果 CStudent 类的 szname 的定义不是“char szname[20] ”而是“string szname”,是否可以?为什么?用文件流类的 put 和 get 成员函数读写文件可以用 ifstream 和 fstream 类的 get 成员函数(继承自 istream 类)从文件中一次读取一个字节,也可以用 ofstream 和 fstream 类的 put 成员函数(继承自 ostream 类) 向文件中一次写入一个字节。

例题:编写一个 mycopy 程序,实现文件复制的功能。用法是在“命令提示符”窗口输入:

mycopy 源文件名 目标文件名

就能将源文件复制到目标文件。例如:

mycopy src.dat dest.dat

即将 src.dat 复制到 dest.dat。如果 dest.dat 原本就存在,则原来的文件会被覆盖。

解题的基本思路是每次从源文件读取一个字节,然后写入目标文件。程序如下:[+++]文件存放于磁盘中,磁盘的访问速度远远低于内存。如果每次读一个字节或写一个字节都要访问磁盘,那么文件的读写速度就会慢得不可忍受。因此, *** 作系统在接收到读文件的请求时,哪怕只要读一个字节,也会把一片数据(通常至少是 512 个字节,因为磁盘的一个扇区是 512 B)都读取到一个 *** 作系统自行管理的内存缓冲区中,当要读下一个字节时,就不需要访问磁盘,直接从该缓冲区中读取就可以了。

*** 作系统在接收到写文件的请求时,也是先把要写入的数据在一个内存缓冲区中保存起来,等缓冲区满后,再将缓冲区的内容全部写入磁盘。关闭文件的 *** 作就能确保内存缓冲区中的数据被写入磁盘。

尽管如此,要连续读写文件时,像 mycopy 程序那样一个字节一个字节地读写,还是不如一次读写一片内存区域快。每次读写的字节数最好是 512 的整数倍。 总结

以上是内存溢出为你收集整理的C++二进制文件的读取和写入(精华版)全部内容,希望文章能够帮你解决C++二进制文件的读取和写入(精华版)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
C++二进制文件的读取和写入(精华版)_C_内存溢出

C++二进制文件的读取和写入(精华版)

C++二进制文件的读取和写入(精华版),第1张

概述用文本方式存储信息不但浪费空间,而且不便于检索。例如,一个学籍管理程序需要记 我们先来说一下为什么要使用二进制文件,它比文本文件有哪些好处。

用文本方式存储信息不但浪费空间,而且不便于检索。例如,一个学籍管理程序需要记录所有学生的学号、姓名、年龄信息,并且能够按照姓名查找学生的信息。程序中可以用一个类来表示学生:
class CStudent{    char szname[20];  //假设学生姓名不超过19个字符,以 '
#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;}
' 结尾 char szID[l0]; //假设学号为9位,以 '
#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))) { //一直读到文件结束        int readedBytes = infile.gcount(); //看刚才读了多少字节        cout << s.szname << " " << s.age << endl;       }    infile.close();    return 0;}
' 结尾 int age; //年龄};
如果用文本文件存储学生的信息,文件可能是如下样子:
Micheal Jackson 110923412 17
Tom Hanks 110923413 18

这种存储方式不但浪费空间,而且查找效率低下。因为每个学生的信息所占用的字节数不同,所以即使文件中的学生信息是按姓名排好序的,要用程序根据名字进行查找仍然没有什么好办法,只能在文件中从头到尾搜索。

如果把全部的学生信息都读入内存并排序后再查找,当然速度会很快,但如果学生数巨大,则把所有学生信息都读人内存可能是不现实的。

可以用二进制的方式来存储学生信息,即把 CStudent 对象直接写入文件。在该文件中,每个学生的信息都占用 sizeof(CStudent) 个字节。对象写入文件后一般称作“记录”。本例中,每个学生都对应于一条记录。该学生记录文件可以按姓名排序,则使用折半查找的效率会很高。

读写二进制文件不能使用前面提到的类似于 cin、cout 从流中读写数据的方法。这时可以调用 ifstream 类和 fstream 类的 read 成员函数从文件中读取数据,调用 ofstream 和 fstream 的 write 成员函数向文件中写入数据。用 ostream::write 成员函数写文件ofstream 和 fstream 的 write 成员函数实际上继承自 ostream 类,原型如下:

ostream & write(char* buffer,int count);

该成员函数将内存中 buffer 所指向的 count 个字节的内容写入文件,返回值是对函数所作用的对象的引用,如 obj.write(...) 的返回值就是对 obj 的引用。

write 成员函数向文件中写入若干字节,可是调用 write 函数时并没有指定这若干字节要写入文件中的什么位置。那么,write 函数在执行过程中到底把这若干字节写到哪里呢?答案是从文件写指针指向的位置开始写入。

文件写指针是 ofstream 或 fstream 对象内部维护的一个变量。文件刚打开时,文件写指针指向文件的开头(如果以 ios::app 方式打开,则指向文件末尾),用 write 函数写入 n 个字节,写指针指向的位置就向后移动 n 个字节。

下面的程序从键盘输入几名学生的姓名和年龄(输入时,在单独的一行中按 Ctrl+Z 键再按回车键以结束输入。假设学生姓名中都没有空格),并以二进制文件形式存储,成为一个学生记录文件 students.dat。

例子,用二进制文件保存学生记录:
#include <iostream>#include <fstream>using namespace std;int main(int argc,char* argv[]){    if (argc != 3) {        cout << "file name missing!" << endl;        return 0;    }    ifstream infile(argv[l],ios::binary | ios::in);  //以二进制读模式打开文件    if (!infile) {        cout << "Source file open error." << endl;        return 0;    }    ofstream outfile(argv[2],ios::binary | ios::out);  //以二进制写模式打开文件    if (!outfile) {        cout << "New file open error." << endl;        infile.close();  //打开的文件一定要关闭        return 0;    }    char c;    while (infile.get(c))  //每次读取一个字符        outfile.put(c);  //每次写入一个字符    outfile.close();    infile.close();    return 0;}
输入:
Tom 60↙
Jack 80↙
Jane 40↙
^Z↙

则形成的 students.dat 为 72 字节,用“记事本”程序打开呈现乱码:

Tom烫烫烫烫烫烫烫烫 Jack烫烫烫烫烫烫烫? Jane烫烫烫烫烫烫烫?


第 13 行指定文件的打开模式是 ios::out|ios::binary,即以二进制写模式打开。在 windows平台中,用二进制模式打开是必要的,否则可能出错,原因会在《文件的文本打开方式和二进制打开方式的区别》一节中介绍。

第 15 行将 s 对象写入文件。s 的地址就是要写入文件的内存缓冲区的地址。但是 &s 不是 char * 类型,因此要进行强制类型转换。

第 16 行,文件使用完毕一定要关闭,否则程序结束后文件的内容可能不完整。用 istream::read 成员函数读文件ifstream 和 fstream 的 read 成员函数实际上继承自 istream 类,原型如下:

istream & read(char* buffer,int count);

该成员函数从文件中读取 count 个字节的内容,存放到 buffer 所指向的内存缓冲区中,返回值是对函数所作用的对象的引用。

如果想知道一共成功读取了多少个字节(读到文件尾时,未必能读取 count 个字节),可以在 read 函数执行后立即调用文件流对象的 gcount 成员函数,其返回值就是最近一次 read 函数执行时成功读取的字节数。gcount 是 istream 类的成员函数,原型如下:

int gcount();

read 成员函数从文件读指针指向的位置开始读取若干字节。文件读指针是 ifstream 或 fstream 对象内部维护的一个变量。文件刚打开时,文件读指针指向文件的开头(如果以ios::app 方式打开,则指向文件末尾),用 read 函数读取 n 个字节,读指针指向的位置就向后移动 n 个字节。因此,打开一个文件后连续调用 read 函数,就能将整个文件的内容读取出来。

下面的程序将前面创建的学生记录文件 students.dat 的内容读出并显示。程序的输出结果是:
Tom 60
Jack 80
Jane 40

第 18 行,判断文件是否已经读完的方法和 while(cin>>n) 类似,归根到底都是因为 istream 类重载了 bool 强制类型转换运算符。

第 19 行只是演示 gcount 函数的用法,删除该行对程序运行结果没有影响。

思考题:关于 students.dat 的两个程序中,如果 CStudent 类的 szname 的定义不是“char szname[20] ”而是“string szname”,是否可以?为什么?用文件流类的 put 和 get 成员函数读写文件可以用 ifstream 和 fstream 类的 get 成员函数(继承自 istream 类)从文件中一次读取一个字节,也可以用 ofstream 和 fstream 类的 put 成员函数(继承自 ostream 类) 向文件中一次写入一个字节。

例题:编写一个 mycopy 程序,实现文件复制的功能。用法是在“命令提示符”窗口输入:

mycopy 源文件名 目标文件名

就能将源文件复制到目标文件。例如:

mycopy src.dat dest.dat

即将 src.dat 复制到 dest.dat。如果 dest.dat 原本就存在,则原来的文件会被覆盖。

解题的基本思路是每次从源文件读取一个字节,然后写入目标文件。程序如下:文件存放于磁盘中,磁盘的访问速度远远低于内存。如果每次读一个字节或写一个字节都要访问磁盘,那么文件的读写速度就会慢得不可忍受。因此, *** 作系统在接收到读文件的请求时,哪怕只要读一个字节,也会把一片数据(通常至少是 512 个字节,因为磁盘的一个扇区是 512 B)都读取到一个 *** 作系统自行管理的内存缓冲区中,当要读下一个字节时,就不需要访问磁盘,直接从该缓冲区中读取就可以了。

*** 作系统在接收到写文件的请求时,也是先把要写入的数据在一个内存缓冲区中保存起来,等缓冲区满后,再将缓冲区的内容全部写入磁盘。关闭文件的 *** 作就能确保内存缓冲区中的数据被写入磁盘。

尽管如此,要连续读写文件时,像 mycopy 程序那样一个字节一个字节地读写,还是不如一次读写一片内存区域快。每次读写的字节数最好是 512 的整数倍。 总结

以上是内存溢出为你收集整理的C++二进制文件的读取和写入(精华版)全部内容,希望文章能够帮你解决C++二进制文件的读取和写入(精华版)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1231702.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存