本文最后更新于:2021年1月28日 下午
概览:C语言与C++读写文件,简单操作事例。
代码全部运行于VS2017
文件分为两种:文本文件与二进制文件。
- 文本文件:文件以ASCII码的形式存储在计算机中
- 二进制文件:文件以二进制的形式存储在计算机中,一般不能直接读懂。
C语言读写文件
打开文件 - fopen
C语言使用fopen函数打开文件
fopen位于stdio.h
中,
1
| FILE *fopen( const char *filename, const char *mode );
|
写文件 - fwrite
1
| size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
|
写入文件使用fwrite
buffer是指向写入对象的指针
size是要写入对象的大小
count 是要写入对象的数量
stream是文件流。
返回值是成功写入的对象数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| struct Student { int id; int age; char name[32]; bool gender; unsigned int height; };
Student stu[] = {
{ 1,17,"lisa",true,179 },
{ 2,18,"kaly",true,159 },
{ 3,20,"luccy",true,109 },
};
FILE* fp = fopen("test.bin", "wb");
for (int i = 0; i < 3; i++) { fwrite(stu + i, sizeof(Student), 1, fp); }
fclose(fp);
|
读文件 - fread
1
| size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
|
- buffer指存储对象的缓冲区。
- 返回数据是成功读取的对象的数目。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| FILE* fp = fopen("test.bin", "rb");
Student stus;
while (!feof(fp)) { int bytes = fread(&stus, sizeof(stus), 1, fp); if (bytes <= 0) { break; } printf("id=%d,age=%d,name=%s,sex=%s,height=%d\n", stus.id, stus.age, stus.name, (stus.gender ? "male" : "famale"), stus.height); }
fclose(fp);
|
其他函数
int feof(FILE *stream);
:检查文件流是否达到末尾,到末尾为非零值,未到末尾为0.
int ferror(FILE *stream);
:检查文件流是否发生错误。非零值表示发生错误,0表示未发生错误。
C++ 文件输入输出
fstream
头文件中定义了三个类型来支持文件IO:
C++文件I/O基本流程
- 包含头文件
fstream
- 创建流对象
- 打开文件,以各种方式打开文件
- 写/读数据
- 关闭流对象。
使用文件流对象
读写文件时,定义一个文件流对象,然后将对象与文件关联起来。
同时,每个文件流类都定义类一个名为open的成员函数,它会完成一些系统相关操作。
创建文件流对象时,文件名是可选的,如果提供文件名,那么open就会被自动调用。
1 2
| ifstream in(ifile); ofstream out;
|
文件流对象关联文件
对于定义的空文件流对象,可以使用open来将其与文件关联起来。
但是使用open有可能失败,所以加上检测是一个良好的习惯。
1 2 3 4 5 6 7 8
| ofstream out; out.open(ifile + ".copy");
if(out) { 如果open成功,open会设置流的状态,使good()为true }
|
一旦一个文件流与一个文件关联,就会持续保持与对应文件的关联。
对一个已经打开的文件流调用open会失败,随后使用文件流操作都会失败。
要让文件流关联其他文件就要先close()。
当一个fstream对象离开其作用域的时候,与之关联的文件会自动关闭。当fstream对象被销毁时,close会自动被调用。
文件模式
ios::in
:读
ios::out
:写
ios::app
:每次写操作前定位到文件末尾
ios::ate
:打开文件后立即定位到文件末尾
ios::trunc
:截断文件
ios::binary
:以二进制方式进行IO
打开文件时,可以指定文件模式
- 只有ofstream以及fstream可以设定out
- 只有ifstream以及fstream可以设定in
- 只有当out被设定时才能设定trunc
- 只要trunc没被设定,就可以设定app
- app模式下,即使没有显式指定out,文件也是用输出方式打开的
- 默认情况下,以out模式打开,文件也会被截断。而为了保留out模式打开文件下的内容,必须同时指定app模式,这样会将数据追加写入道文件末尾,或者同时指定In,打开文件同时进行读写操作。
- ate与binary可用于任何类型的文件流对象下,且可以与其他任何文件模式组合使用。
以out模式打开文件,文件的内容会被丢弃。(截断指丢弃文件内容)
而ofstream out("file")
就是默认以out模式打开,直接会截断文件。
https://www.cnblogs.com/jianyungsun/archive/2011/02/19/1958587.html
普通方式读写文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| void writeFile() { ofstream ofs; ofs.open("person.txt",ios::out);
ofs << "你好,我来自火星" << endl; ofs << "我来侵略地球了,需要宿主" << endl; ofs.close(); }
void readFile() {
ifstream ifs; ifs.open("person.txt", ios::in); if (!ifs.is_open()) { cout << "文件打开失败" << endl; return; }
string buf; while (getline(ifs, buf)) { cout << buf << endl; }
ifs.close();
}
|
读取文件的一些方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| void readFile() {
ifstream ifs; ifs.open("person.txt", ios::in); string buf; while (getline(ifs, buf)) { cout << buf << endl; }
ifs.close();
} char buf[1024] = { 0 }; while (ifs >> buf) { cout << buf << endl; }
char buf[1024] = { 0 }; while (ifs.getline(buf, sizeof(buf))) { cout << buf << endl; }
|
二进制方式读写文件
二进制方式写文件主要利用流对象调用成员函数write
函数原型 :ostream& write(const char * buffer,int len);
- 字符指针buffer指向内存中一段存储空间。len是读写的字节数。
二进制方式读文件主要利用流对象调用成员函数read
函数原型:istream& read(char *buffer,int len);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| class Person { public: char m_name[64]; int m_age; };
void bwrite() { ofstream out; out.open("person.bin", ios::out | ios::binary);
Person p = { "Colourso", 20 }; Person p1 = { "www",19 }; Person p2 = { "IEEE",21 };
out.write((char*)&p,sizeof(p)); out.write((char*)&p1,sizeof(p1)); out.write((char*)&p2,sizeof(p2));
out.close(); }
void bread() { ifstream in; in.open("person.bin", ios::in | ios::binary);
if (!in.is_open()) { cout << "打开失败" << endl; return; }
Person p;
while (in.read((char*)&p, sizeof(p))) { cout << p.m_name << " " << p.m_age << endl; }
in.close(); }
|
- 若Person类中m_name类型为string时,读取文件会发生一些错误……,暂时不知。