许多其他帖子,例如" 将整个ASCII文件读入C++ std::string "等解释了一些选项,但没有深入描述各种方法的优缺点。我想知道为什么一种方法比另一种更可取?
所有这些方法都使用std::fstream
将文件读入std::string
中。我不确定每种方法的成本和收益。假设这是针对已知大小适中的文件而言,内存可以轻松容纳,显然,不管你如何做,将多TB的文件读入内存都是一个坏主意。
在几次谷歌搜索后,将整个文件读入std::string中最常见的方法涉及使用std::getline
并在每行后附加换行符。这对我来说似乎是不必要的,但是否有性能或兼容性原因使其成为理想选择?
std::string Results;
std::ifstream ResultReader("file.txt");
while(ResultReader)
{
std::getline(ResultReader, Results);
Results.push_back('\n');
}
我另一种方法是更改getline的定界符,使其不是文件中的任何内容。EOF字符似乎不太可能出现在文件中间,因此它似乎是一个可能的选择。这包括一个类型转换,因此至少有一个理由不要这样做,但是这将一次性读取文件,而无需进行字符串连接。假设定界符检查仍然会有一些成本。还有其他好的理由不这样做吗?
std::string Results;
std::ifstream ResultReader("file.txt");
std::getline(ResultReader, Results, (char)std::char_traits<char>::eof());
如果系统将std::char_traits::eof()定义为其他值而不是-1,则可能存在问题,这就是选择使用std::getline
和string::push_pack('\n')
等其他方法的实际原因。
相较于像这个问题中读取整个ASCII文件到C++ std::string的其他方式,它们之间有什么区别?
std::ifstream ResultReader("file.txt");
std::string Results((std::istreambuf_iterator<char>(ResultReader)),
std::istreambuf_iterator<char>());
看起来这是最佳选择。它将几乎所有工作都转移到了标准库上,该库应针对给定平台进行了大量优化。我认为除流的有效性检查和文件结尾外,没有理由进行其他检查。这是否理想,或者有看不见的问题。
标准或某些实现的细节是否提供了推荐一种方法胜过另一种的原因?我是否错过了某种可能在各种情况下都非常理想的方法?
读取整个文件到 std::string
的最简单、最典型、表现最佳且符合标准的方法是什么?
编辑 - 2 这个问题促使我编写了一个小型基准套件。它们采用 MIT 许可证,并可在 github 上获得: https://github.com/Sqeaky/CppFileToStringExperiments
最快 - TellSeekRead 和 CTellSeekRead - 系统提供了易于获取的大小并一次性读取文件。
更快 - Getline 追加和 Eof - 检查字符似乎不会带来任何成本。
快 - RdbufMove 和 Rdbuf - std::move 在发布时似乎没有任何区别。
慢 - Iterator、BackInsertIterator 和 AssignIterator - 迭代器和输入流有些问题。它们在内存中表现很好,但在这里不行。尽管如此,其中一些比其他的更快。
我已添加到目前为止建议的每种方法,包括链接中的方法。如果有人能在 Windows 上或使用其他编译器运行此程序,则会非常感激。我当前无法访问具有 NTFS 的计算机,而且已经注意到这个和编译器细节可能很重要。
至于测量简单性和典型性,我们如何客观地衡量这些?简单性似乎是可行的,可能使用类似 LOC 和圆形度复杂性之类的东西,但某件事是否典型纯粹是主观的。
stat
符合标准,但标准是POSIX。 - user4581301