C++: 文件操作进阶

最后更新:2026-08-26

第40课我们学了异常处理。

现在,我们要深入文件操作——程序持久化数据的核心技能。

无论是配置文件、日志、还是数据库,都离不开文件操作。


1. 文件流概述

(1) 1.1 三个文件流类

C++用三个类处理文件:

功能
std::ifstream 输入文件流(读文件)
std::ofstream 输出文件流(写文件)
std::fstream 输入输出文件流(读写)

(2) 1.2 打开文件

示例:打开文件(难度⭐)

▶ 示例 2:文件操作演示(难度⭐)

CPP
#include <iostream>
#include <fstream>

int main() {
 std::ifstream file("data.txt");
 
 if (!file) {
 std::cerr << "无法打开文件" << std::endl;
 return 1;
 }
 
 std::cout << "文件打开成功" << std::endl;
 file.close();
 
 return 0;
}
▶ 试一试

输出:

TEXT 📖 仅展示
文件打开成功


2. 文本文件读写

(1) 2.1 逐行读取

示例:统计文件行数(难度⭐)

CPP
#include <iostream>
#include <fstream>
#include <string>

int main() {
 std::ifstream file("data.txt");
 std::string line;
 int count = 0;
 
 while (std::getline(file, line)) {
 count++;
 }
 
 std::cout << "文件行数:" << count << std::endl;
 file.close();
 
 return 0;
}

(2) 2.2 格式化读写

示例:读写结构体(难度⭐⭐)

CPP
#include <iostream>
#include <fstream>

struct Student {
 char name[50];
 int age;
 double score;
};

int main() {
 Student s = {"张三", 20, 85.5};
 
 // 写文件
 std::ofstream out("student.txt");
 out << s.name << std::endl;
 out << s.age << std::endl;
 out << s.score << std::endl;
 out.close();
 
 // 读文件
 Student s2;
 std::ifstream in("student.txt");
 in >> s2.name >> s2.age >> s2.score;
 in.close();
 
 std::cout << "姓名:" << s2.name << std::endl;
 std::cout << "年龄:" << s2.age << std::endl;
 std::cout << "成绩:" << s2.score << std::endl;
 
 return 0;
}

⚠️ 警告:



3. 二进制文件

(1) 3.1 为什么用二进制文件?

对比 文本文件 二进制文件
可读性 人类可读 不可读
空间 较大
速度
跨平台 差(字节序问题)

(2) 3.2 读写二进制文件

示例:二进制读写结构体(难度⭐⭐⭐)

CPP
#include <iostream>
#include <fstream>

struct Student {
 char name[50];
 int age;
 double score;
};

int main() {
 Student s = {"张三", 20, 85.5};
 
 // 写二进制文件
 std::ofstream out("student.bin", std::ios::binary);
 out.write(reinterpret_cast<char*>(&s), sizeof(s));
 out.close();
 
 // 读二进制文件
 Student s2;
 std::ifstream in("student.bin", std::ios::binary);
 in.read(reinterpret_cast<char*>(&s2), sizeof(s2));
 in.close();
 
 std::cout << "姓名:" << s2.name << std::endl;
 std::cout << "年龄:" << s2.age << std::endl;
 std::cout << "成绩:" << s2.score << std::endl;
 
 return 0;
}

💡 提示:



4. 随机访问

(1) 4.1 seekg和seekp

随机访问允许你在文件中跳转到任意位置读写。

函数 功能
seekg(pos) 设置读位置
seekp(pos) 设置写位置
tellg() 获取当前读位置
tellp() 获取当前写位置

(2) 4.2 示例:修改文件中间的内容(难度⭐⭐⭐)

CPP
#include <iostream>
#include <fstream>

int main() {
 std::fstream file("data.txt", std::ios::in | std::ios::out);
 
 // 跳转到第10个字节
 file.seekp(10);
 
 // 写入数据(覆盖)
 file << "Hello";
 
 file.close();
 return 0;
}

输出:

TEXT 📖 仅展示
Hello, File!
C++ 文件操作


5. 文件流状态

(1) 5.1 状态标志

文件流有4个状态标志:

标志 说明
good() 一切正常
eof() 到达文件末尾
fail() 逻辑错误(如类型不匹配)
bad() 严重错误(如磁盘故障)

(2) 5.2 清除状态

示例:处理文件结束(难度⭐)

CPP
#include <iostream>
#include <fstream>

int main() {
 std::ifstream file("data.txt");
 std::string line;
 
 while (true) {
 std::getline(file, line);
 
 if (file.eof()) {
 break; // 到达文件末尾
 }
 
 std::cout << line << std::endl;
 }
 
 file.clear(); // 清除状态,才能继续使用
 file.close();
 
 return 0;
}


6. 实战:简单的数据库

▶ 示例 1:学生记录管理(难度⭐⭐⭐)

CPP
#include <iostream>
#include <fstream>
#include <vector>
#include <string>

struct Student {
 int id;
 char name[50];
 int age;
};

void saveStudents(const std::vectorStudent& students, const std::string& filename) {
 std::ofstream file(filename, std::ios::binary);
 for (const auto& s : students) {
 file.write(reinterpret_cast<const char*>(&s), sizeof(s));
 }
}

void loadStudents(std::vectorStudent& students, const std::string& filename) {
 std::ifstream file(filename, std::ios::binary);
 Student s;
 while (file.read(reinterpret_cast<char*>(&s), sizeof(s))) {
 students.push_back(s);
 }
}

int main() {
 std::vector<Student> students = {
 {1, "张三", 20},
 {2, "李四", 21}
 };
 
 // 保存
 saveStudents(students, "students.bin");
 
 // 加载
 std::vectorStudent loaded;
 loadStudents(loaded, "students.bin");
 
 std::cout << "加载了" << loaded.size() << "条记录" << std::endl;
 
 return 0;
}
▶ 试一试

输出:

TEXT 📖 仅展示
加载了2条记录

▶ 示例 3:简单文件读写(难度⭐)

CPP
#include <iostream>
#include <fstream>
#include <string>

int main() {
    // 写入文件
    std::ofstream outFile("test.txt");
    outFile << "Hello, File!" << std::endl;
    outFile << "C++ 文件操作" << std::endl;
    outFile.close();
    
    // 读取文件
    std::ifstream inFile("test.txt");
    std::string line;
    while (std::getline(inFile, line)) {
        std::cout << line << std::endl;
    }
    inFile.close();
    
    return 0;
}
▶ 试一试

输出:

TEXT 📖 仅展示
(程序输出)

预期输出:

TEXT 📖 仅展示
Hello, File!
C++ 文件操作

❓ 常见问题

Q 文本文件和二进制文件哪个好?
A 看需求: - 需要人类可读 → 文本文件 - 需要性能/空间 → 二进制文件 - 需要跨平台 → 文本文件

Q 中文字符怎么处理?
A C++对Unicode支持不好,建议: - 用UTF-8编码保存文本文件 - 用第三方库(如iconv) - 或者只存英文/拼音

Q 文件打不开怎么办?
Aif (!file) 检查,配合异常处理。

📖 小节

知识点 要点
文件流类 ifstream/ofstream/fstream
文本文件 <<>> 操作符
二进制文件 writeread
随机访问 seekg/seekp
状态检查 eof()/fail()/bad()

📝 作业

  1. **基础题 (Difficulty ⭐):用 ofstream 写入一个文本文件(三行内容),再用 ifstream 读取并输出到屏幕。

  2. **进阶题 (Difficulty ⭐⭐):用 fstream 以 ios::binary 模式打开文件,写入一个结构体数组,再读取验证。

  3. **挑战题 (Difficulty ⭐⭐⭐):用 seekg/tellg 实现文件随机访问。创建一个"索引文件"记录每条记录的位置,支持按序号直接跳转到指定记录。



下一课:正则表达式(#42)

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏