包含的头文件是fstream,ifstream是文件输入流,ofstream是文件输出流。 打开文件方式为ofstream fout(file_name, ios::out|...|...)或者ofstream fout; fout.open(file_name, ios::out|...|...)。
打开模式说明ios::in为输入打开文件;文件不存在则打开失败,文件存在则打开。(ifstream默认打开方式)ios:out为输出打开文件;文件不存在则创建打开,文件存在则清空。(ofstream默认打开方式)ios::nocreate文件存在的时候不起作用,文件不存在的时候,强制文件不存在也不创建,此项针对输出文件打开。ios::noreplace不覆盖文件,若打开文件时如果文件存在则失败。文件不存在时,参数无效。文件存在时,此选项对ios::in无效,但是对于ios::out有效,当文件存在时打开失败。ios::binary文件默认是以文本形式打开的,此模式为二进制模式打开。ios::trunc若文件不存在,则无效,若文件存在首先清空里面的内容。ios::app所有的输出附加在文件末尾,读操作与写操作共享指针,具有读文件的特性,与ios::out组合使用的时候不清空文件内容。ios::ate文件指针的初始位置在文件尾。二进制文件比文本文件的好处是占用内存空间小,且便于检索。比如要存放结构体或者类时,文本文件存储的只是单纯的文本,不但浪费空间而且效率低下。因为在结构体或者类中每个对象的占用字节数不同,即使文本文件按照某个值排好序,只能从文件头向文件尾搜索,没有什么其他好办法。 但是用二进制来存储,每个结构体或者类占用的字节数都是相同的,直接将该对象写入文件,称作“记录”,每个对象对应一条记录,按照某个值排序之后可以用比如二分搜索等算法进行检索,这样就快了很多。 读写二进制文件不能用类似于cin cout之类的流数据读取方法,这时需要调用fstream和ofstream的成员函数write向文件中写入数据,fstream和ifstream的成员函数read从文件中读取数据。
ostream & write(char* buffer, int count);
#include <iostream> #include <fstream> #include <string> using namespace std; class MyClass{ public: int a; char b[10]; char c; }; int main() { ofstream fout("out.dat",ios::out | ios::binary); if(!fout.is_open()) exit(1); MyClass mc; while(cin >> mc.a >> mc.b >> mc.c) { fout.write((char*)&mc, sizeof(mc));//mc的地址就是要写入内存文件缓冲区的地址 } fout.close(); return 0; }istream & read(char* buffer, int count); int gcount();
#include <iostream> #include <fstream> #include <string> using namespace std; class MyClass{ public: int a; char b[10]; char c; }; int main() { ifstream fin("out.dat",ios::in | ios::binary); if(!fin.is_open()) exit(1); MyClass mc; while(fin.read((char*)&mc, sizeof(mc))) { int cnt_bytes = fin.gcount();//查看刚才读取了多少字节 cout << cnt_bytes<<endl; cout << mc.a << " "<<mc.b << " "<< mc.c<<endl; } fin.close(); return 0; }为什么在MyClass中b定义为string类型的变量,在读取out.dat文件的时候读不出来呢?
此处要注意的就是在写结构体数据的时候,因为char c变量是字符,因此要注意要在每次输入结构体之后吃掉回车符,否则会导致输入失败,就像我在代码中写的那样,用空格来吃掉前面的空白字符(包括回车 空格等)。
#include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct MyStruct{ int a; char b[10]; char c; }MyStruct; int main() { FILE* fp = fopen("test.dat", "wb+");//读写打开或建立一个二进制文件,允许读和写。 if (!fp) exit(1);//写文件失败 /*写int数据*/ /*int a; while(scanf("%d", &a)) fwrite(&a, sizeof(int), 1, fp);//写入int数据*/ /*写结构体数据*/ MyStruct ms; //先将结构体存储在结构体数组中 //MyStruct ms[4]; //MyStruct *p = ms; /*for(int i = 0; i < 4; i++,p++) { scanf(" %d", &p->a); scanf(" %s", p->b); scanf(" %c",&p->c); }*/ //fwrite(ms, sizeof(MyStruct), 4, fp); //最后写到二进制文件 //直接输入 以ctrl+D 结束输入 while(scanf(" %d %s %c ", &ms.a, ms.b, &ms.c)) //while(scanf(" %d", &ms.a) && scanf(" %s ", ms.b) && scanf(" %c ",&ms.c)) { //每次输入结束之后直接写入二进制文件 fwrite(&ms, sizeof(MyStruct), 1, fp); } fclose(fp); return 0; }需要获取文件大小,否则只能自己主观设定数据长度。并不想C++读取二进制文件那样通过是否读到EOF来确定读取是否结束。
#include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct MyStruct{ int a; char b[10]; char c; }MyStruct; int main() { fp = fopen("test.dat", "rb+");//读写打开一个二进制文件,允许读写数据。 if (!fp) exit(1);//写文件失败 fseek(fp, 0L, SEEK_END);//定位到文件尾 int len = ftell(fp); //获取到文件大小 字节数 rewind(fp);//文件指针复位 到文件头 /*读int数据*/ /*int buffer[100]; memset(buffer, 0, sizeof(buffer)); //数组初始化为0 fread(buffer, sizeof(int), 100, fp);//读取数据到buffer缓冲区中 //读取的时候只能都读出来 或者一次读一个数据 但还是需要知道数据总长度 for(int i = 0; i < len / sizeof(int); i++) printf("%d ", buffer[i]); printf("\n"); int j = 0; while(j < len/sizeof(int)) { fread(&buffer[j], sizeof(int), 1, fp); printf("%d \n",buffer[j]); j++; }*/ /*读结构体数据*/ int j = 0; MyStruct ms[100]; while( j < len /sizeof(MyStruct)) { fread(&ms[j], sizeof(MyStruct), 1, fp); printf("%d %s %c\n", ms[j].a, ms[j].b, ms[j].c); j++; } fclose(fp); return 0; }