C++中写文本/二进制文件的最优雅的方式是什么?

3
我在阅读时发现了一些好的结果,例如:使用迭代器和预分配来读取txt文件或者将其读入容器中。因此,我想知道如何最优雅地将std::string写入文件中?
编辑:在读取时,我可以通过寻找和tellg预先分配字符串的空间,因为我知道字符串的大小,那么我该如何告诉文件系统我想要写多少?

1
你看过文件流吗?http://www.cplusplus.com/reference/iostream/fstream/ - fnokke
对于二进制文件,请考虑使用 boost::serialization - Nim
+1。我喜欢这个问题,也很享受解决这个问题的过程! - Nawaz
3个回答

6
这是一个关于如何输出 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;
}

1
为什么要在结尾加上 outfile.close()?它会在析构函数中自动调用。 - Andriy Tylychko

2
您可以使用适当的重载operator<<函数将字符串写入std::ofstream对象。以下是一个示例:
#include <fstream>
#include <string>

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

1
主要问题在于该过程无法完美地反转。
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 << str.size() << str;

也不会在大小和内容之间放置任何空格,因此,如果内容以数字开头,则在稍后读取时会出现问题。

os << str.size() << '\t' << str;

将起作用。

关于读取大型集合,对于字符串,最好的选择是使用制表符或换行符进行分隔,并在循环中使用std::getline。如果您的任何字符串具有空格,则istream_iterator根本无法工作。

您的替代方案是首先读取标题部分:

  • 字符串数量
  • 每个字符串的大小。

然后从一个大缓冲区中读取数据,通过知道要读取的数量和它们的大小,您可以预先分配缓冲区。

写入二进制意味着将原始字节写入文件。这类似于C中的fwrite函数,但您不需要指定两个大小,只需要一个大小,即您将要写入的字节数。

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

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

以这种方式编写数字的最大优点不仅在于它更高效,而且无需插入任何分隔符,因此将其读回变得相对简单。

缺点是,如果文件中存在任何错误,则需要特殊的解释器才能读取文件。

总之,这些都是问题。

所有这些问题的优雅解决方案都作为 boost 库的一部分提供了 archive and serialize

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接