一、标准文件流读写(ifstream/ofstream)

必备头文件

必须引入 <fstream>(文件流核心头文件),配合 <iostream><string> 使用。

1. 写文件(ofstream)语法

核心格式

// 1. 创建写文件流对象,打开文件(不存在则创建,存在则清空原有内容)
ofstream 流对象名("文件路径/文件名");

// 2. 向文件写入内容,用法和cout完全一致
流对象名 << 要写入的内容 << endl;

// 3. 操作完成后关闭文件
流对象名.close();

示例

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    // 打开test.txt,准备写入
    ofstream fout("test.txt");
    // 写入内容,换行用endl
    fout << "Happy" << endl;
    fout << "New Year";
    // 关闭文件
    fout.close();
    return 0;
}

2. 读文件(ifstream)语法

核心格式

// 1. 创建读文件流对象,打开已存在的文件
ifstream 流对象名("文件路径/文件名");

// 2. 读取文件内容,两种核心读取方式
// 方式1:>> 运算符,按空格/换行分隔读取,自动跳过空白符
流对象名 >> 变量;

// 方式2:getline函数,逐行读取,保留行内空格,读到换行符为止
getline(流对象名, 字符串变量);

// 3. 操作完成后关闭文件
流对象名.close();

示例

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    // 打开test.txt,准备读取
    ifstream fin("test.txt");
    string s1, s2;
    // >> 读取到第一个空白符(换行)为止
    fin >> s1;
    // getline 读取剩余整行
    getline(fin, s2);
    // 关闭文件
    fin.close();
    // 输出结果,对应真题第3题
    cout << s1 << "|" << s2;
    return 0;
}

考点

  1. 写入对象必须匹配:必须用ofstream创建的流对象(如fout)执行<<写入,不能用cout写入(错误写法:ofstream file("data.txt"); cout<<"Hello"; 无法写入文件,只会和往常一场输出在控制台)。
  2. >>getline 的区别

    • >> 以空格、换行、制表符为分隔符,读取后会残留换行符在缓冲区
    • getline 读取整行,直到换行符为止,会吃掉换行符;
    • >>后执行getline 会读取>>后的换行符,导致无法正常输入数据。
  3. >> 读取数字的特性:自动跳过所有空格、换行符,无论内容是否分行,都能按顺序读取。
  4. 逐行读取完整文件while (getline(流对象, line)) 可以循环读取文件的每一行,直到文件末尾。
  5. 文件关闭:文件操作完成后必须调用close()关闭文件,避免资源泄漏。

二、C风格freopen 标准输入输出重定向

核心说明

通过freopen函数将标准输出流stdout(对应cout)、标准输入流stdin(对应cin) 重定向到指定文件,之后所有cin都会从该文件读取,cout输出的内容都会写入文件,而非屏幕。

必备头文件

必须引入 <cstdio>(freopen函数所在头文件),配合 <iostream> 使用。

核心语法格式

// 1. 重定向标准输出到文件:"w"代表写入模式,文件不存在则创建,存在则清空
freopen("文件路径/文件名", "w", stdout);
// 2. 重定向标准输入到文件:"r"代表读取模式,文件不存在则创建,存在则清空
freopen("文件路径/文件名", "r", stdin);

// 3. 正常使用cout输出,内容会写入文件,而非屏幕
// 4. 正常使用cin输入,会从文件读取内容,而非键盘

// 5. 操作完成后关闭文件,恢复标准输出
fclose(stdout);

示例

#include <iostream>
#include <cstdio>
using namespace std;

int main() {
    // 将cout的输出重定向到log.txt
    freopen("log.txt", "w", stdout);
    // 此内容会写入log.txt,而非屏幕
    cout << "Welcome to GESP!" << endl;
    // 将cin的输入重定向到log.txt
    freopen("log.txt", "r", stdin);
    // 从log.txt读取字符串
    string s;
    cin >> s;
    // 关闭文件
    fclose(stdout);
    return 0;
}

考点

  1. 重定向后cout才生效:只有执行了freopen重定向后,cout的内容才会写入文件,未重定向时cout只会输出到屏幕。
  2. 打开模式:写入文件必须用"w"模式,代表只写、创建/清空文件。
  3. 必须关闭:重定向后必须用fclose(stdout)关闭文件,刷新缓冲区,确保内容全部写入。

三、C++流缓冲区rdbuf 重定向

核心说明

通过修改cout的流缓冲区(rdbuf),将cout的输出目标切换到文件流,实现输出重定向,相比freopen更灵活,可随时恢复cout到屏幕输出。

必备头文件

必须引入 <fstream><iostream>,无需额外C语言头文件。

核心语法格式

// 1. 创建文件输出流,打开目标文件
ofstream 流对象名("文件路径/文件名");

// 2. 保存cout原有的屏幕缓冲区地址
streambuf* 原缓冲区名 = cout.rdbuf();

// 3. 将cout的缓冲区切换为文件流的缓冲区,后续cout输出到文件
cout.rdbuf(流对象名.rdbuf());

// 4. 正常使用cout输出,内容会写入文件
cout << 要写入的内容 << endl;

// 5. 操作完成后,恢复cout到原屏幕缓冲区
cout.rdbuf(原缓冲区名);

// 6. 关闭文件流
流对象名.close();

示例

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    // 创建文件流,打开log.txt
    ofstream log_file("log.txt");
    // 保存cout原有的屏幕缓冲区
    streambuf* org_cout = cout.rdbuf();
    // 切换cout到文件缓冲区
    cout.rdbuf(log_file.rdbuf());
    // 内容写入log.txt
    cout << "Happy Spring!" << endl;
    // 恢复cout到屏幕输出
    cout.rdbuf(org_cout);
    // 关闭文件
    log_file.close();
    return 0;
}

考点

  1. 必须保存原缓冲区:重定向前必须保存cout的原缓冲区地址,否则后续无法恢复cout到屏幕输出。
  2. 切换缓冲区后cout才生效:只有执行cout.rdbuf(文件流.rdbuf())后,cout才会输出到文件,未切换时cout仅输出到屏幕。
  3. 必须恢复缓冲区:文件操作完成后,必须将cout的缓冲区恢复为原有值,避免后续cout无法正常输出到屏幕。

无效写入错误写法示例:

// 错误写法:仅创建文件流,但未修改cout的输出目标
ofstream outFile("log.txt");
cout << "Welcome to GESP!" << endl; // 内容仅输出到屏幕,不会写入文件
outFile.close();

核心错误:创建了文件流,但既没有用文件流对象执行<<写入,也没有对cout做任何重定向,cout始终输出到屏幕,最终文件为空。

注意总共有三套语法体系,喜欢混起来考,分清楚每一种的流程

标签: none

评论已关闭