主要问题是这个过程并没有完美地逆转。
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。
您可以以文本或二进制模式写入,它会恢复您存储它的方式。它甚至会为你“深度”写指针。