C++ 文件操作速查手册

一、核心头文件与基础类

1. 必备头文件

  • <fstream>:所有文件流操作的核心头文件,包含 ifstream/ofstream/fstream 三类核心文件流类;
  • <iostream>:提供流基类和基础输入输出能力(如 cin/cout),文件流类均继承自其基类;
  • <string>:用于处理文件路径字符串、读写的文本内容;
  • <cstdio>:补充文件重命名、删除等高级操作(兼容 C 标准库)。

2. 核心文件流类

  • std::ifstream:只读文件流,专门用于从文件读取数据(文本 / 二进制均可),默认以 ios::in 模式打开;
  • std::ofstream:只写文件流,专门用于向文件写入数据(文本 / 二进制均可),默认以 ios::out | ios::trunc 模式打开;
  • std::fstream:读写文件流,支持同时读取和写入文件,默认以 ios::in | ios::out 模式打开。

二、文件打开模式

文件打开模式用于指定文件的操作规则,可通过 | 组合多个模式,所有模式均属于 std::ios_base::openmode 类型:

  1. ios::in
    • 功能:以只读方式打开文件,文件不存在则打开失败;
    • 适用场景:读取配置文件、文本内容等只读操作,是 ifstream 的默认模式;
    • 常用组合:ios::in | ios::binary(二进制只读模式)。
  2. ios::out
    • 功能:以只写方式打开文件,文件不存在则自动创建,文件存在则清空原有内容;
    • 适用场景:写入新文件、覆盖原有文件内容,是 ofstream 的默认模式;
    • 常用组合:ios::out | ios::app(追加写模式)。
  3. ios::app
    • 功能:追加写入模式,所有写入内容都会添加到文件末尾,不会清空原有内容;
    • 适用场景:日志文件写入、累计数据记录等需要保留历史内容的场景。
  4. ios::binary
    • 功能:二进制模式打开文件,不处理换行符(Windows 下 \r\n/Linux 下 \n)等特殊字符,直接读写原始字节;
    • 适用场景:图片、视频、自定义结构体等非文本数据的读写。
  5. ios::trunc
    • 功能:打开文件时清空原有内容,ios::out 模式默认包含此属性;
    • 注意:与 ios::app 冲突,同时指定时 app 优先级更高。
  6. ios::ate
    • 功能:打开文件后,文件指针直接定位到文件末尾,可通过指针操作移动到其他位置;
    • 典型用法:快速获取文件总大小(定位到末尾后调用 tellg())。

三、核心函数说明(签名 + 功能 + 示例)

1. 文件打开与关闭

(1)构造函数直接打开
  • 签名(以 ifstream 为例):std::ifstream::ifstream(const std::string& path, std::ios_base::openmode mode = ios::in)
  • 功能:创建流对象的同时打开指定路径的文件,一步完成对象初始化和文件打开;
cpp 复制代码
// 只读打开文本配置文件(默认ios::in模式)
std::ifstream config_in("config.txt");
// 追加模式打开日志文件(ios::out + ios::app)
std::ofstream log_out("app.log", std::ios::out | std::ios::app);
(2)open () 显式打开
  • 签名:void std::ifstream::open(const std::string& path, std::ios_base::openmode mode = ios::in)
  • 功能:为已创建的空流对象绑定并打开指定文件,适用于需要延迟打开文件的场景;
cpp 复制代码
std::fstream data_fs;
// 读写+二进制模式打开数据文件
data_fs.open("data.bin", std::ios::in | std::ios::out | std::ios::binary);
(3)is_open () 检查打开状态
  • 签名:bool std::ifstream::is_open() const
  • 功能:判断文件是否成功打开,返回 true 表示成功,false 表示失败(路径错误、权限不足等);
cpp 复制代码
std::ifstream in("test.txt");
if (!in.is_open()) {
    std::cerr << "文件打开失败:test.txt" << std::endl;
    return 1; // 异常退出
}
(4)close () 关闭文件
  • 签名:void std::ifstream::close()
  • 功能:关闭已打开的文件,释放系统文件句柄资源;
cpp 复制代码
std::ofstream out("log.txt");
// 写入内容后显式关闭
out.close();

2. 文本文件读写

(1)getline () 逐行读取
  • 签名:std::istream& std::getline(std::istream& is, std::string& str)
  • 功能:从输入流中读取一行文本(直到换行符,不包含换行符)到字符串变量中;
cpp 复制代码
std::ifstream in("config.txt");
std::string line;
// 逐行读取直到文件末尾
while (std::getline(in, line)) {
    std::cout << "读取行:" << line << std::endl;
}
(2)>> 运算符 按空白符读取
  • 功能:从文件流中读取数据(单词、数字等),自动跳过空格、换行、制表符等空白符;
cpp 复制代码
std::ifstream in("num.txt"); // 文件内容:10 20 30 40
int num;
// 逐个读取整数
while (in >> num) {
    std::cout << "读取数字:" << num << std::endl;
}
(3)get () 单字符读取
  • 签名:std::istream& std::istream::get(char& c)
  • 功能:读取单个字符(包括空白符、换行符)到字符变量中,保留文件原始格式;
cpp 复制代码
std::ifstream in("test.txt");
char ch;
// 逐字符读取并输出
while (in.get(ch)) {
    std::cout << ch;
}
(4)<< 运算符 格式化写入
  • 功能:与 std::cout 用法完全一致,向文件流写入格式化数据(字符串、数字、浮点数等);
cpp 复制代码
std::ofstream out("log.txt");
out << "程序启动时间:" << "2026-01-26" << std::endl;
out << "用户ID:" << 1001 << " | 分数:" << 95.5 << std::endl;
(5)put () 单字符写入
  • 签名:std::ostream& std::ostream::put(char c)
  • 功能:向文件流写入单个字符,支持链式调用;
cpp 复制代码
std::ofstream out("char.txt");
// 链式写入字符,最终文件内容:Hello\n
out.put('H').put('e').put('l').put('l').put('o').put('\n');

3. 二进制文件读写

(1)read () 二进制读取
  • 签名:std::istream& std::istream::read(char* buffer, std::streamsize count)
  • 功能:从文件流中读取指定字节数的二进制数据到缓冲区;
cpp 复制代码
// 读取4字节整数(二进制模式)
std::ifstream in("data.bin", std::ios::in | std::ios::binary);
int num;
// 强制转换为char*,读取int大小的字节数
in.read(reinterpret_cast<char*>(&num), sizeof(num));
std::cout << "读取的整数:" << num << std::endl;
(2)write () 二进制写入
  • 签名:std::ostream& std::ostream::write(const char* buffer, std::streamsize count)
  • 功能:将缓冲区中的指定字节数的二进制数据写入文件流;
cpp 复制代码
// 写入自定义结构体(二进制模式)
struct Student { int id; char name[20]; float score; };
std::ofstream out("stu.bin", std::ios::out | std::ios::binary);
Student s = {1001, "张三", 95.5f};
out.write(reinterpret_cast<const char*>(&s), sizeof(s));

4. 文件指针与随机访问

文件流通过「读指针(get)」和「写指针(put)」实现随机访问,读指针操作函数以 g 结尾,写指针以 p 结尾:

(1)seekg () 移动读指针
  • 签名 1(绝对位置):std::istream& std::istream::seekg(std::streampos pos)
  • 签名 2(相对位置):std::istream& std::istream::seekg(std::streamoff off, std::ios_base::seekdir dir)
  • 功能:移动读指针到指定位置,dir 可选基准位置:
    • ios::beg:从文件开头偏移;
    • ios::cur:从当前指针位置偏移;
    • ios::end:从文件末尾偏移;
cpp 复制代码
std::ifstream in("test.txt");
in.seekg(0, std::ios::end); // 指针移到文件末尾(用于获取文件大小)
in.seekg(10, std::ios::beg); // 指针移到文件开头后第10字节
(2)tellg () 获取读指针位置
  • 签名:std::streampos std::istream::tellg() const
  • 功能:返回当前读指针的位置(字节数,从文件开头算起);
cpp 复制代码
std::ifstream in("test.txt");
in.seekg(0, std::ios::end);
std::streampos file_size = in.tellg(); // 获取文件总字节数
std::cout << "文件大小:" << file_size << " 字节" << std::endl;
(3)seekp () 移动写指针
  • 功能与签名同 seekg(),区别是操作写指针,适用于写文件或读写文件场景;
cpp 复制代码
std::fstream fs("data.bin", std::ios::in | std::ios::out | std::ios::binary);
fs.seekp(5); // 写指针移到第5字节位置(绝对位置)
(4)tellp () 获取写指针位置
  • 功能与签名同 tellg(),区别是返回写指针的当前位置;
cpp 复制代码
std::ofstream out("test.txt");
out << "Hello";
std::streampos pos = out.tellp(); // 返回5("Hello"共5字节)

5. 错误处理函数

文件操作需检查流状态,避免操作失败导致程序异常:

(1)eof()
  • 签名:bool std::ios::eof() const
  • 功能:判断是否到达文件末尾(EOF),返回 true 表示正常读取到末尾;
cpp 复制代码
std::ifstream in("test.txt");
std::string line;
while (std::getline(in, line)) {}
if (in.eof()) {
    std::cout << "文件读取完成(正常到达末尾)" << std::endl;
}
(2)fail()
  • 签名:bool std::ios::fail() const
  • 功能:判断是否发生非致命错误(如格式错误:读取整数时读到字母);
cpp 复制代码
if (in.fail()) {
    std::cerr << "文件读取格式错误(非致命)" << std::endl;
}
(3)bad()
  • 签名:bool std::ios::bad() const
  • 功能:判断是否发生致命错误(如文件损坏、磁盘故障、流被破坏);
cpp 复制代码
if (in.bad()) {
    std::cerr << "文件读取致命错误(如文件损坏)" << std::endl;
}
(4)clear()
  • 签名:void std::ios::clear(std::ios_base::iostate state = std::ios_base::goodbit)
  • 功能:清除流的错误状态(如 eof()true 后,需调用 clear() 才能继续操作);
cpp 复制代码
in.clear(); // 清除所有错误状态
in.seekg(0); // 重置读指针到文件开头

6. 高级文件操作

(1)文件重命名
  • 函数:std::rename(来自 <cstdio>);
  • 功能:修改文件名,成功返回 0,失败返回非 0;
cpp 复制代码
#include <cstdio>
if (std::rename("old.txt", "new.txt") != 0) {
    std::cerr << "文件重命名失败" << std::endl;
}
(2)文件删除
  • 函数:std::remove(来自 <cstdio>);
  • 功能:删除指定文件,成功返回 0,失败返回非 0;
cpp 复制代码
#include <cstdio>
if (std::remove("tmp.txt") != 0) {
    std::cerr << "文件删除失败" << std::endl;
}
(3)获取文件大小
  • 实现方式:结合 seekg()tellg()
cpp 复制代码
std::ifstream in("test.bin", std::ios::binary);
in.seekg(0, std::ios::end); // 指针移到末尾
int size = in.tellg(); // 获取字节数
in.seekg(0, std::ios::beg); // 移回开头,方便后续操作
std::cout << "文件大小:" << size << " 字节" << std::endl;

四、常用场景完整示例

场景 1:逐行读取文本配置文件

cpp 复制代码
#include <fstream>
#include <iostream>
#include <string>
using namespace std;

int main() {
    // 打开配置文件
    ifstream config_in("config.conf");
    if (!config_in.is_open()) {
        cerr << "配置文件打开失败:config.conf" << endl;
        return 1;
    }

    // 逐行读取并输出
    string line;
    cout << "===== 配置文件内容 =====" << endl;
    while (getline(config_in, line)) {
        cout << line << endl;
    }

    // 检查读取状态
    if (config_in.eof()) {
        cout << "\n配置文件读取完成" << endl;
    }

    config_in.close();
    return 0;
}

场景 2:追加写入日志文件

cpp 复制代码
#include <fstream>
#include <iostream>
#include <string>
using namespace std;

int main() {
    // 追加模式打开日志文件
    ofstream log_out("app.log", ios::out | ios::app);
    if (!log_out) {
        cerr << "日志文件打开失败" << endl;
        return 1;
    }

    // 写入日志内容
    log_out << "【INFO】程序启动成功 | 时间:2026-01-26 15:30:00" << endl;
    log_out << "【DEBUG】用户ID:1001 | 操作:登录" << endl;

    log_out.close();
    cout << "日志写入完成" << endl;
    return 0;
}

场景 3:二进制读写结构体数据

cpp 复制代码
#include <fstream>
#include <iostream>
using namespace std;

// 自定义数据结构体
struct UserData {
    int id;
    char username[16];
    double balance;
};

int main() {
    // 1. 写入二进制数据
    ofstream out("user_data.bin", ios::out | ios::binary);
    if (!out) {
        cerr << "写入文件打开失败" << endl;
        return 1;
    }
    UserData user = {1002, "李四", 5000.50};
    out.write(reinterpret_cast<const char*>(&user), sizeof(user));
    out.close();

    // 2. 读取二进制数据
    ifstream in("user_data.bin", ios::in | ios::binary);
    if (!in) {
        cerr << "读取文件打开失败" << endl;
        return 1;
    }
    UserData read_user;
    in.read(reinterpret_cast<char*>(&read_user), sizeof(read_user));
    in.close();

    // 输出读取结果
    cout << "用户ID:" << read_user.id << endl;
    cout << "用户名:" << read_user.username << endl;
    cout << "余额:" << read_user.balance << endl;

    return 0;
}

场景 4:批量打开并读取多个文件

cpp 复制代码
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
using namespace std;

int main() {
    // 待打开的文件列表
    vector<string> file_list = {"file1.txt", "file2.txt", "file3.txt"};
    // 存储多个读流对象(使用移动语义,ifstream不可拷贝)
    vector<ifstream> file_ins;

    // 批量打开文件
    for (const string& path : file_list) {
        ifstream in(path);
        if (!in) {
            cerr << "跳过失败文件:" << path << endl;
            continue;
        }
        file_ins.push_back(move(in)); // 移动语义存入容器
    }

    // 批量读取每个文件
    for (int i = 0; i < file_ins.size(); ++i) {
        cout << "\n===== 读取文件:" << file_list[i] << " =====" << endl;
        string line;
        while (getline(file_ins[i], line)) {
            cout << line << endl;
        }
        file_ins[i].close();
    }

    return 0;
}

五、关键注意事项

  1. 打开文件后必须检查 is_open():路径错误、权限不足、文件不存在等都会导致打开失败,未检查会引发后续操作崩溃;
  2. 流对象不可拷贝:ifstream/ofstream/fstream 均禁用拷贝构造和赋值,批量管理时需用 std::move 实现移动;
  3. 二进制模式必加 ios::binary:读写图片、结构体等非文本数据时,不加此模式会导致换行符被篡改,数据错误;
  4. 错误状态需清除:调用 eof()/fail()true 后,流会进入错误状态,需用 clear() 清除后才能继续操作;
  5. 及时关闭文件:虽然流对象析构时会自动关闭文件,但显式调用 close() 能及时释放文件句柄,避免资源泄露;
  6. 路径分隔符:跨平台代码优先使用 /(Windows 和 Linux 均支持),避免 \(Windows 专属,需转义为 \\)。

总结

  1. 文件操作核心是「流对象 + 打开模式 + 读写方法」,选对类(ifstream/ofstream/fstream)和模式是基础;
  2. 文本文件用 getline()/<< 读写,二进制文件用 read()/write() + ios::binary
  3. 随机访问依赖 seekg()/tellg()/seekp()/tellp(),错误处理需结合 eof()/fail()/clear()
  4. 批量操作多个文件时,用 vector 存储流对象并配合移动语义,避免拷贝错误。
相关推荐
C++ 老炮儿的技术栈2 小时前
不调用C++/C的字符串库函数,编写函数strcmp
c语言·开发语言·c++·人工智能·windows·git·visual studio
茉莉玫瑰花茶2 小时前
脚手架介绍
c++
Hgfdsaqwr2 小时前
内存泄漏检测与防范
开发语言·c++·算法
茉莉玫瑰花茶3 小时前
C++17 详细特性解析(中)
开发语言·c++
安全二次方security²3 小时前
CUDA C++编程指南(7.19&20)——C++语言扩展之Warp投票函数和Warp匹配函数
c++·人工智能·nvidia·cuda·投票函数·匹配函数·vote
Trouvaille ~3 小时前
【Linux】进程信号(三):信号捕捉与操作系统运行原理
linux·运维·服务器·c++·操作系统·信号·中断
哈哈不让取名字3 小时前
分布式日志系统实现
开发语言·c++·算法
知无不研3 小时前
实现一个整形栈
c语言·数据结构·c++·算法
ShineWinsu4 小时前
对于C++:模版初阶的解析
开发语言·c++·面试·笔试·函数··模版