C++ 提供了标准库中的 fstream 系列类来完成文件操作,相关的函数封装在这些类的成员方法中,能够满足文本文件、二进制文件的读写、定位、状态判断等各类需求。不同函数对应不同的操作场景,合理搭配使用可以高效完成文件处理任务。

C++ 文件操作基础类介绍
C++ 文件操作主要依赖三个核心类,分别承担不同的功能:
- ifstream:输入文件流类,专门用于从文件中读取数据,对应输入操作。
- ofstream:输出文件流类,专门用于向文件中写入数据,对应输出操作。
- fstream:通用文件流类,同时支持文件的读取和写入操作,功能更全面。
这三个类都定义在 <fstream> 头文件中,使用时需要先包含该头文件。
文件打开与关闭函数
打开文件:open() 函数
open() 是文件流类的成员函数,用于建立程序和磁盘文件的关联,函数原型如下:
void open(const char* filename, ios::openmode mode);
参数说明:
- filename:要打开的文件路径,可以是相对路径或绝对路径。
- mode:打开模式,多个模式可以用位或运算符 | 组合。
常见的打开模式如下:
| 模式标识 | 含义 |
|---|---|
| ios::in | 以读取模式打开文件,ifstream 默认使用该模式 |
| ios::out | 以写入模式打开文件,ofstream 默认使用该模式,会清空已有内容 |
| ios::app | 追加模式,写入的数据会添加到文件末尾,不会清空原有内容 |
| ios::ate | 打开文件后定位到文件末尾 |
| ios::trunc | 如果文件已存在,先清空文件内容再打开 |
| ios::binary | 以二进制模式打开文件,不处理换行符等转义 |
以下是使用 open() 函数打开文件的示例:
#include <fstream>
#include <iostream>
using namespace std;
int main() {
ofstream outFile;
// 以写入和追加模式打开 test.txt 文件
outFile.open("test.txt", ios::out | ios::app);
if (!outFile.is_open()) {
cout << "文件打开失败" << endl;
return 1;
}
// 后续写入操作...
return 0;
}
关闭文件:close() 函数
close() 函数用于断开文件流和磁盘文件的关联,释放相关资源,函数原型为:
void close();
使用完成后调用 close() 是良好的编程习惯,虽然程序结束时系统会自动回收资源,但显式关闭可以避免资源占用问题。示例:
#include <fstream>
using namespace std;
int main() {
ifstream inFile;
inFile.open("data.txt", ios::in);
if (inFile.is_open()) {
// 读取操作...
inFile.close(); // 显式关闭文件
}
return 0;
}
文本文件读写函数
写入函数:<< 运算符与 put() 函数
对于文本文件的写入,最常用的方式是重载的 << 运算符,用法和 cout 输出到控制台一致,支持各类基本数据类型的写入。另外 put() 函数可以写入单个字符。
#include <fstream>
#include <iostream>
using namespace std;
int main() {
ofstream fout("text.txt", ios::out | ios::trunc);
if (fout) {
int num = 100;
string str = "Hello C++ File";
// 使用 << 写入不同数据类型
fout << "数字:" << num << endl;
fout << "字符串:" << str << endl;
// 使用 put 写入单个字符
fout.put('A');
fout.put('n');
fout.close();
}
return 0;
}
读取函数:>> 运算符、get() 与 getline() 函数
文本文件读取可以使用 >> 运算符,它会自动跳过空白字符(空格、换行、制表符等),读取到下一个空白字符为止。如果需要读取整行或者单个字符,可以使用 get() 和 getline() 函数。
get():读取单个字符,函数原型为 int get(); 或者 istream& get(char& c);getline():读取一行内容,直到遇到换行符,函数原型为 istream& getline(char* s, streamsize n); 或者全局 getline(istream& is, string& str);
读取示例:
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main() {
ifstream fin("text.txt", ios::in);
if (fin) {
string line;
// 逐行读取文件内容
while (getline(fin, line)) {
cout << "读取到行:" << line << endl;
}
// 读取单个字符示例
fin.clear(); // 清空之前的状态,因为上面已经读到文件末尾
fin.seekg(0, ios::beg); // 定位到文件开头
char c;
while (fin.get(c)) {
cout << "字符:" << c << endl;
}
fin.close();
}
return 0;
}
二进制文件读写函数
二进制文件读写需要使用 ios::binary 模式打开,对应的读写函数为 write() 和 read()。
二进制写入:write() 函数
write() 函数原型为:
ostream& write(const char* buffer, streamsize size);
参数 buffer 是要写入数据的指针,size 是要写入的字节数,通常需要将数据类型转换为 char* 指针。
二进制读取:read() 函数
read() 函数原型为:
istream& read(char* buffer, streamsize size);
参数含义和 write() 对应,buffer 是存放读取数据的缓冲区,size 是要读取的字节数。
二进制文件操作示例,存储和读取结构体数据:
#include <fstream>
#include <iostream>
#include <cstring>
using namespace std;
struct Student {
int id;
char name[20];
float score;
};
int main() {
// 写入二进制文件
ofstream fout("student.dat", ios::out | ios::binary | ios::trunc);
if (fout) {
Student stu1 = {1, "张三", 95.5f};
fout.write((const char*)&stu1, sizeof(Student));
fout.close();
}
// 读取二进制文件
ifstream fin("student.dat", ios::in | ios::binary);
if (fin) {
Student stu2;
fin.read((char*)&stu2, sizeof(Student));
cout << "学号:" << stu2.id << endl;
cout << "姓名:" << stu2.name << endl;
cout << "成绩:" << stu2.score << endl;
fin.close();
}
return 0;
}
文件定位与状态判断函数
文件定位函数
文件读写过程中可以通过定位函数移动文件指针的位置,主要有以下几个:
seekg():输入流定位函数,用于 ifstream 和 fstream 的读取定位,原型为 istream& seekg(streampos pos); 和 istream& seekg(streamoff off, ios::seekdir dir);seekp():输出流定位函数,用于 ofstream 和 fstream 的写入定位,用法和 seekg() 一致。tellg():返回当前输入文件指针的位置。tellp():返回当前输出文件指针的位置。
其中 dir 的取值有:
- ios::beg:从文件开头计算偏移量
- ios::cur:从当前位置计算偏移量
- ios::end:从文件末尾计算偏移量
定位示例:
#include <fstream>
#include <iostream>
using namespace std;
int main() {
fstream file("test.txt", ios::in | ios::out | ios::trunc);
if (file) {
file << "abcdefghijklmn" << endl;
// 定位到文件开头第3个字符位置
file.seekg(3, ios::beg);
char c;
file.get(c);
cout << "第3个字符是:" << c << endl; // 输出 d
// 获取当前指针位置
streampos pos = file.tellg();
cout << "当前指针位置:" << pos << endl;
file.close();
}
return 0;
}
状态判断函数
文件操作过程中可以通过状态函数判断操作是否成功,常见的状态函数有:
is_open():判断文件是否成功打开,返回 bool 值。good():判断文件流状态是否正常,所有状态位都为0时返回 true。fail():判断最近一次操作是否失败,比如类型不匹配、打开失败等,返回 true 表示失败。bad():判断文件流是否发生致命错误,比如磁盘损坏等,返回 true 表示出现严重错误。eof():判断是否已经读到文件末尾,返回 true 表示到达末尾。
状态判断示例:
#include <fstream>
#include <iostream>
using namespace std;
int main() {
ifstream fin("nonexist.txt", ios::in);
if (!fin.is_open()) {
cout << "文件打开失败" << endl;
}
fin.open("test.txt", ios::in);
if (fin.good()) {
char c;
while (!fin.eof()) {
fin.get(c);
if (fin.fail()) break; // 读取失败则退出
cout << c;
}
// 清空状态位,方便后续操作
fin.clear();
fin.close();
}
return 0;
}
常见问题说明
在使用 C++ 文件操作函数时,需要注意几个常见的问题:
- 打开文件后一定要判断打开是否成功,避免后续操作崩溃。
- 文本模式和二进制模式的区别:文本模式下换行符可能会被转义,二进制模式不会,处理非文本文件时务必使用二进制模式。
- 文件指针定位后如果后续操作失败,需要调用 clear() 函数清空状态位,否则后续操作会一直失败。
- 结构体写入二进制文件时,如果结构体包含指针成员,写入的只是指针的值而不是指针指向的内容,读取后指针会失效,这种情况需要单独处理指针指向的数据。