【问题标题】:What is the most elegant way to write a text/binary file with c++?用 C++ 编写文本/二进制文件最优雅的方法是什么?
【发布时间】:2011-03-10 08:19:40
【问题描述】:

我在阅读时发现了一些不错的结果,例如:Read txt with iterators and preallocationread into containers。所以我想知道如何将最优雅的 std::string 写入文件?

编辑:读取时我可以通过 seek 和 tellg 为字符串预分配空间,因为我知道字符串的大小,我怎么能告诉文件系统我想写多少?

【问题讨论】:

标签: c++ string file file-io text-files


【解决方案1】:

这里有一个关于如何输出std::string 的小例子,但你应该认真阅读fstream

#include <iostream>
#include <fstream>
#include <string>

int main(int argc, char *argv[])
{

  std::string s("writemeout");
  std::ofstream outfile("output.txt");
  if(!outfile.is_open()) {
    std::cerr << "Couldn't open 'output.txt'" << std::endl;
    return -1;
  }

  outfile << s << std::endl;
  outfile.close();
  return 0;
}

【讨论】:

  • 为什么最后是outfile.close()?它在析构函数中自动调用
【解决方案2】:

您可以使用operator&lt;&lt; 函数的适当重载将字符串写入std::ofstream 对象。这是一个例子:

#include <fstream>
#include <string>

int main() {
    std::string s( "Hello, World!" );
    std::ofstream f( "hello.txt" );
    if ( !f.fail() )
        f << s;
}

【讨论】:

    【解决方案3】:

    主要问题是这个过程并没有完美地逆转。

    std::ofstream ofs; // presumed open
    ofs << v1 << v2 << v3 << v4 << v5; // some different variables
    ofs.close();
    
    std::ifsteram ifs; // open to same stream
    ifs >> r1 >> r2 >> r3 >> r4 >> r5; // variables of same types as above
    

    您可能认为这会奏效,但很可能不会。写入文本流时没有正式的分隔符,您必须手动插入它们才能知道一个标记何时结束而另一个标记何时开始。

    通常对于字符串,假设它们不包含换行符或制表符,然后在回读时,这些通常用作分隔符。

    写一个字符串以便你可以读回它的最“完美”的方法是先写它的大小然后写它的内容。即使你使用 iostream:

    os &lt;&lt; str.size() &lt;&lt; str;

    不会在大小和内容之间放置任何空格,因此如果内容以数字开头,您稍后再阅读时会遇到麻烦。

    os &lt;&lt; str.size() &lt;&lt; '\t' &lt;&lt; str;

    会起作用的。

    关于阅读大集合,最好的字符串是使用制表符分隔或行分隔并在循环中使用 std::getline。如果您的任何字符串有空格,istream_iterator 将根本不起作用。

    您的替代方法是首先阅读标题部分: - 字符串数 - 每个字符串的大小。

    然后仅从一个大缓冲区中读取数据,并通过了解您将要读取的数量及其大小,您可以预先分配您的缓冲区。

    写入二进制意味着将原始字节写入文件。这类似于 C 中的 fwrite 函数,不同之处在于您没有指定两种大小,只指定一种大小,即您将写入的字节数。

    您需要解决以下问题: - 如果您不打开二进制流,Windows 将在您编写的每个 ASCII 10 字符前面插入一个 ASCII 13 字符。 - 如果您按字节编写数字,请注意字节序和大小问题,如果它们将被读回。解决此问题的最佳方法是将字节序放在输出的标题部分,然后以本机格式写入。假设大多数时候这将是您使用的平台,因此它更有效。

    int x;
    os.write( &x, sizeof(int) );
    

    以这种方式写入数字的一大好处不仅是时间效率更高,而且不需要插入任何类型的分隔符,因此读取它们变得相对简单。

    缺点是如果文件中有任何错误,您将需要一个特殊的解释器来读回文件。

    无论如何,这些都是问题。

    所有这一切的优雅解决方案作为 boost 库的一部分提供,archive and serialize

    您可以以文本或二进制模式写入,它会恢复您存储它的方式。它甚至会为你“深度”写指针。

    【讨论】:

      猜你喜欢
      • 2010-09-16
      • 2014-05-16
      • 1970-01-01
      • 2013-05-07
      • 1970-01-01
      • 2010-11-01
      • 1970-01-01
      • 2021-10-22
      • 1970-01-01
      相关资源
      最近更新 更多