在 C++ 中,可以使用 I/O 流以及流运算符 >>
和 <<
来完成对文件的读取和写入。 在读取或写入文件时,这些运算符应用于表示硬盘驱动器上的文件的类的实例。 这种基于流的方法具有巨大的优势:从 C++ 的角度来看,读取或写入的内容是什么并不重要,无论是文件、数据库、控制台,还是通过网络连接到的另一台 PC。 因此,知道如何使用流运算符编写文件可以转移到其他领域。
I/O 流类
C++ 标准库提供了 ios_base 类。 此类充当所有与 I/O 流兼容的类的基类,例如 basic_ofstream 和 basic_ifstream。 此示例将使用用于读取/写入字符的专用类型 ifstream
和 ofstream
。
ofstream
表示*输出文件流*,可以使用插入运算符<<
访问它。ifstream
表示*输入文件流*,可以使用提取运算符>>
访问它。
这两种类型都在头文件 <fstream>
中定义。
继承自 ios_base
的类可以被认为是写入时的数据接收器或读取时的数据源,完全独立于数据本身。 这种面向对象的方法使诸如 关注点分离 和 依赖注入 之类的概念易于实现。
一个简单的例子
这个示例程序非常简单:它创建一个 ofstream
,写入它,创建一个 ifstream
,然后从中读取
#include <iostream> // cout, cin, cerr etc...
#include <fstream> // ifstream, ofstream
#include <string>
int main()
{
std::string sFilename = "MyFile.txt";
/******************************************
* *
* WRITING *
* *
******************************************/
std::ofstream fileSink(sFilename); // Creates an output file stream
if (!fileSink) {
std::cerr << "Canot open " << sFilename << std::endl;
exit(-1);
}
/* std::endl will automatically append the correct EOL */
fileSink << "Hello Open Source World!" << std::endl;
/******************************************
* *
* READING *
* *
******************************************/
std::ifstream fileSource(sFilename); // Creates an input file stream
if (!fileSource) {
std::cerr << "Canot open " << sFilename << std::endl;
exit(-1);
}
else {
// Intermediate buffer
std::string buffer;
// By default, the >> operator reads word by workd (till whitespace)
while (fileSource >> buffer)
{
std::cout << buffer << std::endl;
}
}
exit(0);
}
此代码可在 GitHub 上找到。 编译并执行它时,您应该获得以下输出

(Stephan Avenwedde, CC BY-SA 4.0)
这是一个简化的、对初学者友好的示例。 如果您想在自己的应用程序中使用此代码,请注意以下事项
- 文件流在程序结束时自动关闭。 如果您要继续执行,则应通过调用
close()
方法手动关闭它们。 - 这些文件流类(通过多个级别)继承自 basic_ios,它重载了
!
运算符。 这使您可以实现一个简单的检查,以确定是否可以访问流。 在 cppreference.com 上,您可以找到有关何时此检查会(和不会)成功的概述,并且您可以实现进一步的错误处理。 - 默认情况下,
ifstream
在空格处停止并跳过它。 要逐行读取直到到达 EOF,请使用getline(...)
方法。 - 对于读取和写入二进制文件,请将
std::ios::binary
标志传递给构造函数:这可以防止 EOL 字符附加到每行。
从系统的角度编写
写入文件时,数据将写入系统的内存中写入缓冲区。 当系统接收到系统调用 sync 时,此缓冲区的内容将写入硬盘驱动器。 此机制也是您不应在未告知系统的情况下移除 USB 记忆棒的原因。 通常,sync 由守护程序定期调用。 如果您确实想安全起见,您也可以手动调用 sync
#include <unistd.h> // needs to be included
sync();
总结
在 C++ 中读取和写入文件并不复杂。 此外,如果您知道如何处理 I/O 流,那么您也知道(原则上)如何处理任何类型的 I/O 设备。 各种 I/O 设备的库使您可以使用流运算符进行轻松访问。 这就是为什么了解 I/O 流如何工作是有益的。
评论已关闭。