跳转到内容

文件与基本读写

参考《NOI大纲》

  • 文件的基本概念、文本文件的基本操作
  • 文本文件类型与二进制文件类型
  • 文件重定向、文件读写等操作

文件输入输出

文件的概念

在 C++ 中,每一个文件都是一个有序的字节流,每个文件都是以文件结束标志(EOF) 结束,如果要操作某个文件,步骤如下:

  1. 以指定的模式(读或写)打开文件
  2. 对文件进行读、写操作
  3. 操作完成后,关闭该文件

在 C++ 中有 fstreamfreopen 两种方式用于文件输入输出。

fropen函数

freopen 是 C 语言中的函数,用于重新定向标准输入输出流到指定的文件。它可以用于改变程序默认的输入输出流,使程序从文件中读取输入或将输出写入文件。使用 freopen 需要引入 <cstdio> 头文件。

看下面一个示例:

#include <cstdio>
#include <iostream>
using namespace std;
int main() {
// 读入指定文件内容
freopen("problem.in", "r", stdin);
// 输出到文件
freopen(("problem.out"), "w", stdout);
int a, b, c;
cin >> a >> b >> c;
cout << "三数之和为 " << a + b + c << endl;
// 关闭标准输入/输出流
fclose(stdin);
fclose(stdout);
return 0;
}

可以看到,一旦我们使用 freopen 函数将标准的 stdin / stdout 重定向后,当我们使用 cin / out / scanf / printf 等函数进行输入输出时,都将被定向到指定的文件。

fstream函数

fstream 是 C++ 中的文件输入输出流类。它提供了打开、读取和写入文件的功能。你可以使用 ifstream 类进行文件读取操作,使用 ofstream 类进行文件写入操作,或者使用 fstream 类同时进行读写操作。

需要注意的是,当我们使用 fstream 函数在读写文件时,就不能使用 C 风格的输入输出 scanfprinft 了。

#include <fstream>
using namespace std;
int main() {
// 读入
ifstream fin("problem.in");
// 输出
ofstream fout ("problem.out");
int a, b, c;
cin >> a >> b >> c;
cout << "三数之和为 " << a + b + c << endl;
// 关闭标准输入/输出流
fin.close();
fout.close();
return 0;
}

freopenfstream 比较

fstream 是 C++ 的标准库,而 freopen 是 C 语言的函数,在 C++ 中,两者都可以使用。

相对来说,fstream 提供了更多的功能和灵活性,适用于 C++ 中对文件进行读写操作的场景。而 freopen 则是用于重定向标准输入输出流的 C 语言函数,在 C++ 中也可以使用。具体使用哪种方式取决于你的需求和编程环境。


【需重新梳理一遍】

C++ 文件读写与 Competitive Programming 相关内容

C++ 中进行文件读写是一项重要技能,尤其是在需要本地测试或者题目要求文件输入输出时。本文将详细讲解以下几个部分:

  1. 文件的基本概念与文本文件的基本操作
  2. 文本文件与二进制文件的区别及操作
  3. 文件重定向的概念与实现
  4. 文件读写技巧在竞赛编程中的应用

1. 文件的基本概念与文本文件的基本操作

什么是文件?

  • 文件是存储在磁盘或其他存储设备上的数据集合。
  • C++ 文件操作通过 fstream 头文件中的类来实现,包括:
    • ifstream(输入文件流):用于读文件
    • ofstream(输出文件流):用于写文件
    • fstream(文件流):同时支持读写文件

文本文件的基本操作

文本文件是以 ASCII 或 UTF-8 格式存储的文件,主要存储可见字符

1. 读文件(ifstream

#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream inputFile("input.txt"); // 打开文件以读取数据
if (!inputFile.is_open()) {
cerr << "无法打开文件!" << endl;
return 1;
}
int x, y;
inputFile >> x >> y; // 从文件中读取两个整数
cout << "读取的数是: " << x << "" << y << endl;
inputFile.close(); // 关闭文件
return 0;
}

2. 写文件(ofstream

#include <iostream>
#include <fstream>
using namespace std;
int main() {
ofstream outputFile("output.txt"); // 打开文件以写入数据
if (!outputFile.is_open()) {
cerr << "无法打开文件!" << endl;
return 1;
}
int result = 42;
outputFile << "结果是: " << result << endl; // 将数据写入文件
outputFile.close(); // 关闭文件
return 0;
}

3. 读写文件(fstream

fstream 同时支持读写操作,常用于需要对文件进行多次访问的场景:

#include <iostream>
#include <fstream>
using namespace std;
int main() {
fstream file("data.txt", ios::in | ios::out | ios::trunc); // 读写模式打开,清空原内容
if (!file.is_open()) {
cerr << "文件无法打开!" << endl;
return 1;
}
// 写入数据
file << "Hello World" << endl;
// 将文件指针移到文件开头
file.seekg(0, ios::beg);
// 读取数据
string data;
getline(file, data);
cout << "读取内容: " << data << endl;
file.close();
return 0;
}

2. 文本文件与二进制文件的区别及操作

区别:

  1. 文本文件

    • 数据存储为字符格式,可用文本编辑器打开查看。
    • 数据经过编码和解码,通常较大。
  2. 二进制文件

    • 数据以二进制格式存储,存储的是原始数据。
    • 更紧凑,读取更快,但不能直接用文本编辑器查看。

文本文件与二进制文件的读写

文本文件读写(默认模式)

文本文件是 C++ 文件流的默认模式。

ofstream outputFile("text.txt"); // 默认文本写入
outputFile << "12345" << endl; // 输出字符串,按字符存储
outputFile.close();

二进制文件读写

二进制文件使用 ios::binary 标志,数据直接存储为原始格式

示例:写入和读取二进制文件

#include <iostream>
#include <fstream>
using namespace std;
int main() {
// 写二进制文件
ofstream outFile("binary.dat", ios::binary); // 以二进制模式打开
int a = 12345;
outFile.write((char*)&a, sizeof(a)); // 写入原始数据
outFile.close();
// 读二进制文件
ifstream inFile("binary.dat", ios::binary);
int b;
inFile.read((char*)&b, sizeof(b)); // 读取原始数据
cout << "读取的数是: " << b << endl;
inFile.close();
return 0;
}

3. 文件重定向的概念与实现

文件重定向的概念

文件重定向是一种将程序的标准输入/输出流重定向到文件的技术。

  • 输入重定向:让 cin 从文件中读取数据,而不是键盘。
  • 输出重定向:让 cout 将结果写入文件,而不是输出到屏幕。

freopen 实现文件重定向

重定向输入与输出

#include <iostream>
using namespace std;
int main() {
freopen("input.txt", "r", stdin); // 将标准输入重定向到 input.txt
freopen("output.txt", "w", stdout); // 将标准输出重定向到 output.txt
int a, b;
cin >> a >> b; // 从 input.txt 读取数据
cout << a + b << endl; // 将结果输出到 output.txt
return 0;
}

重定向的优点:

  1. 代码无需修改:
    使用 cincout 的代码无需更改,只需添加 freopen

  2. 适合竞赛场景:
    本地测试时,将测试数据放入文件,可以快速调试。


4. 文件读写在竞赛编程中的应用

Competitive Programming 中,文件操作主要用于:

  1. 测试本地样例数据:
    将输入放入 input.txt,程序从文件读取,输出到 output.txt,方便本地调试。

  2. 处理大规模数据:
    对于较大的输入输出数据,文件 I/O 可以提高运行效率。

  3. 平台要求:
    某些竞赛平台可能要求程序使用文件输入输出。

推荐模板:文件重定向

#include <iostream>
using namespace std;
int main() {
freopen("input.txt", "r", stdin); // 重定向标准输入到 input.txt
freopen("output.txt", "w", stdout); // 重定向标准输出到 output.txt
// 竞赛代码示例
int n, sum = 0;
cin >> n; // 从 input.txt 读取数据
for (int i = 0; i < n; i++) {
int x;
cin >> x;
sum += x;
}
cout << "总和: " << sum << endl; // 输出到 output.txt
return 0;
}

5. 常见错误与注意事项

  1. 文件路径问题:

    • 确保文件与程序在同一目录。
    • 使用完整路径时,路径要正确。
  2. 文件未关闭:

    • 使用 close() 关闭文件,释放资源。
  3. 忘记重定向标准输入输出:

    • 文件重定向时,要使用正确的 freopen 语句。
  4. 文本模式与二进制模式混淆:

    • 文本文件和二进制文件要分清操作模式。
  5. 平台限制:

    • 某些在线评测系统可能不支持 freopen

总结

在 C++ 的文件读写中:

  1. 使用 ifstreamofstream 实现文本文件的读取和写入。
  2. 使用 ios::binary 打开二进制文件,直接读写原始数据。
  3. 使用 freopen 重定向标准输入输出,适合竞赛本地测试。

掌握这些技巧后,可以在竞赛编程中高效处理文件读写任务,提高程序调试效率!