【问题标题】:How to read any file safely into a string? [duplicate]如何安全地将任何文件读入字符串? [复制]
【发布时间】:2012-09-13 23:02:38
【问题描述】:

可能重复:
What is the best way to slurp a file into a std::string in c++?

我正在尝试为 C++ 模仿 PHP 的 file_get_contents() 函数。

但是,当我将 char 数组转换为字符串时,它会在 nullbyte 处停止:

fread(charbuf, 1, file_size, fp);
string str(charbuf);

如何将字符串初始化为静态大小的数组,并将文件内容直接读取到该容器?另外,我如何检查它的错误,例如,如果没有足够的内存来初始化该字符串。这也可以让我摆脱我目前正在使用的临时内存分配,我想摆脱它。

安全性如何?是否有可能许多进程同时读取同一个文件和/或其中一个进程在我读取它时同时写入它?如何避免此类事情发生?

希望你能回答“字符串不是二进制容器”以外的其他方式。

我要求重新提出这个问题:“显然,这个问题与以往一样重要:两年后,两个最有效的解决方案仍然将整个文件内容复制到内存中,并且优化器无法忽略此副本。这是一种非常不令人满意的情况。– Konrad Rudolph 2010 年 10 月 25 日 6:25" What is the best way to read an entire file into a std::string in C++?有额外的字符串副本吗?

【问题讨论】:

  • 使用ifstream有什么问题吗? stackoverflow.com/questions/2912520/…
  • @loler,这是否只分配了与 file_size 相同的内存量?还是它会创建字符串的临时副本? (例如,如果文件为 100MB,是否在程序的某个阶段分配了 200MB?)。
  • 是不是很有趣,这个“完全重复”有 -2 票,但重复有 +18 票?我猜它并不像你想象的那样完全重复。
  • 不,这并不好笑,也不出人意料。有助于感知问题质量的一件事是对其进行的研究。关于这个主题至少有两个很好的问题;这个问题可能因为您没有找到而被否决。
  • 另外,字符串一个二进制容器。它可以很好地包含 NUL,并且它对存储的内容不做任何假设,例如,甚至不考虑字节序。

标签: c++ string file


【解决方案1】:
std::ifstream fin("somefile.txt");
std::stringstream buffer;
buffer << fin.rdbuf();
std::string result = buffer.str();

这个 sn-p 会将你所有的文件放入 std::string

【讨论】:

  • 还有额外的内存分配:您将(复制)缓冲区转换为字符串...我想避免所有这些,直接将其读取到字符串容器中,无需任何附加分配。
  • 目前的编译器有 rvo-value 优化。这里的临时对象没问题。
  • @Rookie 老实说,您或多或少关心一个分配,除非您使用的是嵌入式系统,否则它不会让您减慢那么多。
  • @Rookie:我能理解这种情绪。然而,许多 看起来 像在复制数据的 C++ 结构实际上并非如此。 (这不是因为 C++ 愚蠢,相反:这是因为 C++ 可以优化一些其他语言无法优化的东西。)优化的第一条规则:测量,优化,测量。
  • @Rookie:这让我们回到了第一点:“我理解这种情绪......”我真的明白。但是您仍然没有衡量您的编译器是否可以优化您的库中的调用。而且,对于像你(和我)这样的完美主义者来说,不幸的是,在关键路径之外,简单性和可读性胜过优化。 (这是一个拥有超过 12 年实践经验的声明。)
【解决方案2】:

希望你能以“字符串不是二进制容器”以外的方式回答。

std::string 二进制容器,但您选择的构造函数将 C 风格的字符串作为参数。尝试不同的构造函数:

std::fread(charbuf, 1, file_size, fp);
std::string str(charbuf, file_size);

编辑:考虑到避免内存分配的要求:

std::string str(file_size, 0);
std::fread(&str[0], 1, file_size, fp);

【讨论】:

  • 这里的问题是我需要分配 charbuf 然后释放它...所以如果我读取 100MB 文件,我会同时分配 200MB 数据(用于 char* 和 std:string)。如果我一次只分配 100MB 的数据,效率会更高。
  • 这似乎与这里的其他人所说的完全一致,它仍在使用临时内存,所以我同时为 100MB 文件分配了 200MB。
  • 我可以以某种方式使用 str.resize() 吗...?好像有这样的功能。
  • @Rookie 因为它不起作用。您不能将fread 转换为std::string,原因很简单:如何使str.size() 返回正确的值? (提示:str.resize() 将用零覆盖所有内容)。
猜你喜欢
  • 2018-11-23
  • 1970-01-01
  • 2011-07-25
  • 2017-11-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-31
  • 1970-01-01
  • 2011-11-16
相关资源
最近更新 更多