如何将文件读入 std::string
,即一次读取整个文件?
文本或二进制模式应由调用者指定。该解决方案应符合标准、可移植且高效。它不应该不必要地复制字符串的数据,并且应该避免在读取字符串时重新分配内存。
一种方法是统计文件大小,调整 std::string
的大小。和 fread()
进入std::string
的const_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/