编辑:在读取时,我可以通过寻找和tellg预先分配字符串的空间,因为我知道字符串的大小,那么我该如何告诉文件系统我想要写多少?
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()
?它会在析构函数中自动调用。 - Andriy Tylychkooperator<<
函数将字符串写入std::ofstream
对象。以下是一个示例:#include <fstream>
#include <string>
int main() {
std::string s( "Hello, World!" );
std::ofstream f( "hello.txt" );
if ( !f.fail() )
f << s;
}
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。
您可以以文本或二进制模式编写,并将恢复您存储的方式。 它甚至会为您“深入”编写指针。
boost::serialization
。 - Nim