c++ - 如何在 C++ 中将整个文件读入 std::string?

标签 c++ string file-io

如何将文件读入 std::string ,即一次读取整个文件?

文本或二进制模式应由调用者指定。该解决方案应符合标准、可移植且高效。它不应该不必要地复制字符串的数据,并且应该避免在读取字符串时重新分配内存。

一种方法是统计文件大小,调整 std::string 的大小。和 fread()进入std::stringconst_cast<char*>()编辑 data() .这需要 std::string的数据是连续的,这不是标准所要求的,但对于所有已知的实现来说似乎都是如此。更糟糕的是,如果以文本模式读取文件,std::string的大小可能不等于文件的大小。

可以使用 std::ifstream 构建完全正确、符合标准且可移植的解决方案的rdbuf()变成 std::ostringstream并从那里进入 std::string .但是,这可能会复制字符串数据和/或不必要地重新分配内存。

  • 是否所有相关的标准库实现都足够聪明,可以避免所有不必要的开销?
  • 还有其他方法吗?
  • 我是否错过了一些已经提供所需功能的隐藏 Boost 功能?


void slurp(std::string& data, bool is_binary)

最佳答案

一种方法是将流缓冲区刷新为单独的内存流,然后将其转换为 std::string(省略错误处理):

std::string slurp(std::ifstream& in) {
    std::ostringstream sstr;
    sstr << in.rdbuf();
    return sstr.str();
}

这非常简洁。但是,正如问题中所述,这会执行冗余拷贝,不幸的是,基本上没有办法删除此拷贝。

不幸的是,避免冗余拷贝的唯一真正解决方案是手动循环读取。由于 C++ 现在已经保证了连续的字符串,因此可以编写以下内容(≥C++17,包括错误处理):

auto read_file(std::string_view path) -> std::string {
    constexpr auto read_size = std::size_t(4096);
    auto stream = std::ifstream(path.data());
    stream.exceptions(std::ios_base::badbit);
    
    auto out = std::string();
    auto buf = std::string(read_size, '\0');
    while (stream.read(& buf[0], read_size)) {
        out.append(buf, 0, stream.gcount());
    }
    out.append(buf, 0, stream.gcount());
    return out;
}

关于c++ - 如何在 C++ 中将整个文件读入 std::string?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/116038/

相关文章:

c++ - QtableWidget header 中的复选框

python - CMAKE 3.9.3 找不到 Boost1.65.1 Boost_Python

javascript - 如何有条件地格式化我的 HTML 表格?

c - 如何检测 C 中的 CLI 特殊字符?

java - 文件类的“尝试使用资源”功能

c - 打开和读取文件失败

c++ - 如何使 StackWalk64() 在 x64 上成功运行?

c++ - 对于所有编译器,C++ 中的 If 语句中的各种条件是否总是具有相同的执行顺序?

java - 我加载 .txt 文件时做错了什么?

java - 为什么下面的例子似乎反驳了 String 是 Java 中的不可变对象(immutable对象)?