在 C++ 中将文件读入到字符串

Jinku Hu 2023年1月30日 2020年12月31日
  1. 使用 istreambuf_iterator 在 C++ 中将文件读入到字符串
  2. 在 C++ 中使用 rdbuf 将文件读入字符串
  3. 使用 fread 将文件读入字符串
  4. 使用 read 将文件读成字符串
在 C++ 中将文件读入到字符串

本文将讲解几种在 C++ 中把文件内容读取到 std::string 的方法。

使用 istreambuf_iterator 在 C++ 中将文件读入到字符串

istreambuf_iterator 是一个输入迭代器,从 std::basic_streambuf 对象中读取连续的字符。因此,我们可以利用 istreambuf_iteratorifstream 流一起使用,并将文件的全部内容读取到 std::string 中。

首先,我们打开一个给定的文件路径作为 ifstream 对象。然后,我们可以将 istreambuf_iterator<char>(input_file) 传递给 string 构造函数,并在第一时间得到我们需要的对象。注意,我们是直接传递 string 构造函数语句,从函数中返回。程序的输出应该是由 filename 变量指定的文件内容。

#include <iostream>
#include <fstream>
#include <sstream>

using std::cout; using std::cerr;
using std::endl; using std::string;
using std::ifstream; using std::ostringstream;

string readFileIntoString(const string& path) {
    ifstream input_file(path);
    if (!input_file.is_open()) {
        cerr << "Could not open the file - '"
             << path << "'" << endl;
        exit(EXIT_FAILURE);
    }
    return string((std::istreambuf_iterator<char>(input_file)), std::istreambuf_iterator<char>());
}

int main()
{
    string filename("input.txt");
    string file_contents;

    file_contents = readFileIntoString(filename);
    cout << file_contents << endl;

    exit(EXIT_SUCCESS);
}

在 C++ 中使用 rdbuf 将文件读入字符串

rdbuf 函数是一个内置的方法,用来返回文件的流缓冲区的指针,这对于使用 << 运算符将文件的全部内容插入到需要的对象中是很有用的。

在下面的例子中,我们构造了一个 ostringstream 对象,在这个对象中插入 rdbuf 函数的返回值。函数本身返回的是 string 对象,所以使用 str 方法来获取最终的返回值。

#include <iostream>
#include <fstream>
#include <sstream>

using std::cout; using std::cerr;
using std::endl; using std::string;
using std::ifstream; using std::ostringstream;

string readFileIntoString2(const string& path) {
    auto ss = ostringstream{};
    ifstream input_file(path);
    if (!input_file.is_open()) {
        cerr << "Could not open the file - '"
             << path << "'" << endl;
        exit(EXIT_FAILURE);
    }
    ss << input_file.rdbuf();
    return ss.str();
}

int main()
{
    string filename("input.txt");
    string file_contents;

    file_contents = readFileIntoString2(filename);
    cout << file_contents << endl;

    exit(EXIT_SUCCESS);
}

使用 fread 将文件读入字符串

另一种读取文件的方法是 C 标准库函数 fread。这种方法需要相对较旧的函数,在现代 C++ 代码库中并不常见,但与以前的方法相比,它在速度方面有优势。

fread 需要四个参数。

  1. 一个指向存储读取数据的缓冲区的指针。
  2. 数据项的大小。
  3. 数据项的数量。
  4. 读取的文件指针。

由于我们要读的是整个文件,所以需要检索文件大小,并通过 Unix 系统调用 stat 实现。检索到文件大小后,我们将其值作为数据元素的大小传递给 fread 函数,并将数据项的数目指定为 1

需要注意的是,打开的文件需要用 fclose 函数调用来关闭,它的唯一参数是文件指针。

#include <iostream>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

using std::cout; using std::cerr;
using std::endl; using std::string;

string readFileIntoString3(const string& path) {
    struct stat sb{};
    string res;

    FILE* input_file = fopen(path.c_str(), "r");
    if (input_file == nullptr) {
        perror("fopen");
    }

    stat(path.c_str(), &sb);
    res.resize(sb.st_size);
    fread(const_cast<char*>(res.data()), sb.st_size, 1, input_file);
    fclose(input_file);

    return res;
}

int main()
{
    string filename("input.txt");
    string file_contents;

    file_contents = readFileIntoString3(filename);
    cout << file_contents << endl;

    exit(EXIT_SUCCESS);
}

使用 read 将文件读成字符串

read 方法是符合 POSIX 标准的函数调用,在各种操作系统上都可以使用,如果程序员懂得有效地运用它,那么它可以成为最灵活的一种方法。fread 本身会在下面调用 read,但这并不能保证在所有情况下都有更快的操作,因为多种因素对这种系统调用的有效使用起着影响。

fread 的主要区别在于,read 需要一个文件描述符参数来指向从哪里读取数据的文件。文件描述符是与程序在执行过程中可能具有的打开的文件流相关联的特殊整数。它可以使用 open 函数调用获得,并以 int 类型存储。read 函数的另外两个参数是指向将存储数据的缓冲区的指针和需要读取的字节数,后者用 fstat 函数调用检索。注意,我们使用 string.data 作为缓冲区来存储读取的文件内容。

#include <iostream>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

using std::cout; using std::cerr;
using std::endl; using std::string;

string readFileIntoString4(const string& path) {
    struct stat sb{};
    string res;

    int fd = open(path.c_str(), O_RDONLY);
    if (fd < 0) {
        perror("open\n");
    }

    fstat(fd, &sb);
    res.resize(sb.st_size);
    read(fd, (char*)(res.data()), sb.st_size);
    close(fd);

    return res;
}

int main()
{
    string filename("input.txt");
    string file_contents;

    file_contents = readFileIntoString4(filename);
    cout << file_contents << endl;

    exit(EXIT_SUCCESS);
}
Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn

相关文章 - C++ File