如何在 C++ 中读取和写入文件

如果您知道如何在 C++ 中使用 I/O 流,那么原则上您可以处理任何类型的 I/O 设备。
47 位读者喜欢这篇文章。
Computer screen with files or windows open

Opensource.com

在 C++ 中,可以使用 I/O 流以及流运算符 >><< 来完成对文件的读取和写入。 在读取或写入文件时,这些运算符应用于表示硬盘驱动器上的文件的类的实例。 这种基于流的方法具有巨大的优势:从 C++ 的角度来看,读取或写入的内容是什么并不重要,无论是文件、数据库、控制台,还是通过网络连接到的另一台 PC。 因此,知道如何使用流运算符编写文件可以转移到其他领域。

I/O 流类

C++ 标准库提供了 ios_base 类。 此类充当所有与 I/O 流兼容的类的基类,例如 basic_ofstreambasic_ifstream。 此示例将使用用于读取/写入字符的专用类型 ifstreamofstream

  • 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 上找到。 编译并执行它时,您应该获得以下输出

这是一个简化的、对初学者友好的示例。 如果您想在自己的应用程序中使用此代码,请注意以下事项

  • 文件流在程序结束时自动关闭。 如果您要继续执行,则应通过调用 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 流如何工作是有益的。

接下来读什么
标签
User profile image.
Stephan 是一位技术爱好者,他欣赏开源对事物如何运作的深刻见解。 Stephan 在工业自动化软件这个主要为专有领域的公司担任全职支持工程师。 如果可能,他会致力于他基于 Python 的开源项目、撰写文章或驾驶摩托车。

评论已关闭。

Creative Commons License此作品已根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.