C++ 文件输入输出库 – <fstream>(手把手讲解)

C++ 文件输入输出库 – 的入门与实战

在 C++ 编程中,处理数据的方式远不止在控制台打印或读取键盘输入。很多时候,我们需要将程序运行的数据持久化保存到磁盘文件中,或者从文件中加载数据进行处理。这时,C++ 提供的文件输入输出库 —— <fstream> 就成了不可或缺的工具。

这个库是标准库的一部分,提供了 ifstream(输入文件流)、ofstream(输出文件流)和 fstream(双向文件流)三种核心类,让你可以像操作 cincout 一样,轻松地读写文件内容。虽然初学者可能会觉得文件操作复杂,但只要掌握基本逻辑,你会发现它其实非常直观。


文件流的核心概念:流与文件的“桥梁”

想象一下,文件就像一个图书馆里的书本,而程序则是读者。<fstream> 就是那个连接你和书本之间的“阅读器”。它把文件的内容变成一串连续的“数据流”,你可以从中读取,也可以向其中写入。

在 C++ 中,ifstream 用于从文件读取数据,ofstream 用于向文件写入数据,而 fstream 可以同时支持读和写。它们都继承自 iostream,因此你熟悉的 >><< 操作符依然可用。

⚠️ 提示:使用文件流前,必须包含头文件 <fstream>


从零开始:创建与写入文件

我们先来一个最简单的例子:创建一个文本文件,并写入几行文字。

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

int main() {
    // 创建一个 ofstream 对象,指定文件名为 "output.txt"
    std::ofstream outFile("output.txt");

    // 检查文件是否成功打开
    if (!outFile.is_open()) {
        std::cerr << "文件打开失败!" << std::endl;
        return 1;
    }

    // 使用 << 操作符向文件写入内容
    outFile << "第一行:Hello, C++ File I/O!" << std::endl;
    outFile << "第二行:这是通过 <fstream> 写入的文本。" << std::endl;
    outFile << "第三行:文件操作其实很简单。" << std::endl;

    // 关闭文件,释放资源
    outFile.close();

    std::cout << "文件写入成功!" << std::endl;

    return 0;
}

代码解析:

  • std::ofstream outFile("output.txt");:创建一个输出文件流,尝试打开 output.txt。如果文件不存在,会自动创建。
  • !outFile.is_open():检查文件是否成功打开。这是防止程序因文件无法访问而崩溃的重要步骤。
  • outFile << ...:使用输出操作符写入数据,和 cout 用法几乎一样。
  • outFile.close();:必须显式关闭文件,否则可能造成数据丢失或资源泄漏。

💡 小贴士:如果你在 IDE 中运行这段代码,运行后会发现项目目录下多了一个 output.txt 文件,打开就能看到写入的内容。


读取文件内容:从磁盘“取书”

现在我们来读取刚才创建的文件。这次用 ifstream

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

int main() {
    // 创建输入文件流,打开 "output.txt"
    std::ifstream inFile("output.txt");

    // 检查文件是否打开成功
    if (!inFile.is_open()) {
        std::cerr << "文件打开失败!" << std::endl;
        return 1;
    }

    std::string line;
    int lineNumber = 1;

    // 逐行读取文件内容
    while (std::getline(inFile, line)) {
        std::cout << "第 " << lineNumber << " 行: " << line << std::endl;
        lineNumber++;
    }

    // 关闭文件
    inFile.close();

    return 0;
}

代码解析:

  • std::getline(inFile, line):这是读取文件的“神器”函数。它会读取一行内容(直到换行符),并存入 line 字符串中。
  • while (std::getline(...)):循环直到文件读完。当文件结束时,getline 会返回 false,循环自动退出。
  • >> 不同,getline 会保留空格和换行符,适合处理整行文本。

读写混合:使用 fstream 实现双向操作

有时候你需要同时读和写同一个文件。比如修改配置文件、日志追加等。这时 fstream 就派上用场了。

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

int main() {
    // 使用 fstream 实现读写功能
    std::fstream file("config.txt", std::ios::in | std::ios::out | std::ios::app);

    if (!file.is_open()) {
        std::cerr << "文件打开失败!" << std::endl;
        return 1;
    }

    // 先写入新内容(追加模式)
    file << "last_update=2024-04-05" << std::endl;

    // 将文件指针重置到开头,准备读取
    file.seekg(0, std::ios::beg);

    std::string line;
    std::cout << "文件当前内容:" << std::endl;

    // 读取并输出所有行
    while (std::getline(file, line)) {
        std::cout << line << std::endl;
    }

    file.close();
    return 0;
}

关键点说明:

  • std::ios::app:追加模式,写入内容会加在文件末尾。
  • file.seekg(0, std::ios::beg):将“读指针”移动到文件开头。seekg 是“seek get”的缩写,用于控制读位置。
  • std::ios::in | std::ios::out:同时启用读和写权限。

✅ 这种方式适合日志记录、配置文件更新等场景。


文件模式详解:选择正确的打开方式

打开文件时,你可以指定不同的模式,决定文件行为。以下是常见模式组合:

模式标志 作用
std::ios::in 以只读方式打开文件(默认)
std::ios::out 以写入方式打开文件,若文件存在则清空内容
std::ios::app 以追加方式打开,写入内容添加到文件末尾
std::ios::ate 打开文件后立即定位到文件末尾
std::ios::binary 以二进制模式打开,用于处理非文本文件(如图片、音频)

📌 示例:std::fstream file("data.bin", std::ios::in | std::ios::binary); 用于读取二进制文件。


实际应用:保存用户信息到文件

我们来做一个更实用的小项目:保存用户信息到文件。

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

struct User {
    std::string name;
    int age;
    std::string email;
};

int main() {
    std::vector<User> users = {
        {"张三", 25, "zhangsan@example.com"},
        {"李四", 30, "lisi@example.com"},
        {"王五", 22, "wangwu@example.com"}
    };

    // 写入用户数据到文件
    std::ofstream outFile("users.txt");
    if (!outFile.is_open()) {
        std::cerr << "无法创建文件!" << std::endl;
        return 1;
    }

    for (const auto& user : users) {
        outFile << user.name << " " << user.age << " " << user.email << std::endl;
    }

    outFile.close();
    std::cout << "用户信息已保存到 users.txt" << std::endl;

    // 读取并显示
    std::ifstream inFile("users.txt");
    if (!inFile.is_open()) {
        std::cerr << "无法打开文件!" << std::endl;
        return 1;
    }

    std::string name;
    int age;
    std::string email;

    std::cout << "\n读取到的用户信息:" << std::endl;
    while (inFile >> name >> age >> email) {
        std::cout << "姓名: " << name << ", 年龄: " << age << ", 邮箱: " << email << std::endl;
    }

    inFile.close();
    return 0;
}

亮点分析:

  • 使用结构体封装用户数据,代码更清晰。
  • >> 操作符按空格分割读取,适合格式固定的文本。
  • 实际项目中,这种数据持久化方式非常常见。

总结与建议

通过本文,我们系统地学习了 C++ 文件输入输出库 —— <fstream> 的核心用法。从最基础的文件创建与写入,到读取、混合读写,再到实际项目中的应用,每一步都围绕“如何让程序与文件对话”展开。

✅ 关键提醒:

  • 每次使用文件流前,务必检查 is_open()
  • 写完文件后,一定要调用 close()
  • 选择正确的打开模式,避免意外覆盖或追加错误。

<fstream> 虽然看似简单,但它是构建完整应用程序的重要一环。无论是保存用户数据、读取配置、生成报告,还是处理日志,它都能胜任。

掌握它,你就迈出了让程序“有记忆”的第一步。别再只让程序在内存中“活一瞬”,而是让它真正“活”在你的电脑里。