如何将未刷新的std::ofstream内容导出存储到std::string中?
实现方案说明
标准库的std::ofstream默认绑定std::filebuf类型的缓冲区,未执行flush的写入数据只会存在filebuf的内部内存缓冲区中,标准库没有提供公开的可移植接口直接读取这部分缓冲区内容,因此无法直接从现有ofstream对象中提取未刷入文件的内容,需要调整实现逻辑来达成需求。
方案1:优先推荐,使用std::ostringstream中转
如果你的someMethod、yetAnotherMethod的参数是std::ostream&(绝大多数场景下的合理设计,而非硬编码为std::ofstream&),可以先把所有输出写入内存字符串流,最后再同步到文件和目标字符串,改造成本极低:
#include <fstream> #include <sstream> #include <string> // 你的原有方法签名只要是接收ostream&就无需修改,比如: // void someMethod(std::ostream& os); // void yetAnotherMethod(std::ostream& os); int main() { std::ostringstream oss; oss << "stuff"; someMethod(oss); oss << "blah"; yetAnotherMethod(oss); // 更多写入操作... // 直接获取所有内容 std::string s = oss.str(); // 同步写入到文件 std::ofstream ofs("somefile.txt"); ofs << s; // 如果需要后续继续写文件,保留ofs对象即可 return 0; }
方案2:使用Tee分流流,同时写入文件和字符串
如果你需要在写入过程中实时同步输出到文件和内存,不需要等到所有操作完成后再写文件,可以自定义一个Tee缓冲区,让输出流同时绑定文件缓冲区和字符串缓冲区:
#include <streambuf> #include <ostream> #include <fstream> #include <sstream> #include <string> class tee_buf : public std::streambuf { private: std::streambuf* buf1; std::streambuf* buf2; protected: virtual int overflow(int c) override { if (c == EOF) return !EOF; int const r1 = buf1->sputc(c); int const r2 = buf2->sputc(c); return r1 == EOF || r2 == EOF ? EOF : c; } virtual int sync() override { int const r1 = buf1->pubsync(); int const r2 = buf2->pubsync(); return r1 == 0 && r2 == 0 ? 0 : -1; } public: tee_buf(std::streambuf* b1, std::streambuf* b2) : buf1(b1), buf2(b2) {} }; class tee_stream : public std::ostream { private: tee_buf tb; public: tee_stream(std::ostream& os1, std::ostream& os2) : std::ostream(&tb), tb(os1.rdbuf(), os2.rdbuf()) {} }; // 原有方法无需修改 int main() { std::ofstream ofs("somefile.txt"); std::ostringstream oss; tee_stream ts(ofs, oss); ts << "stuff"; someMethod(ts); // 直接传入tee流即可 ts << "blah"; yetAnotherMethod(ts); // 更多写入操作... std::string s = oss.str(); // 获取所有写入的内容 return 0; }
注意事项
- 如果你的
someMethod、yetAnotherMethod参数硬编码为std::ofstream&,建议先将参数改为基类std::ostream&,这是C++流操作的最佳实践,适配所有输出流类型。 - 不建议使用依赖特定标准库实现的hack方法直接读取
filebuf的内部缓冲区,这类实现不可移植,在不同编译器/标准库版本下可能失效。
内容的提问来源于stack exchange,提问作者Vada Poche
相关产品推荐
相关产品推荐

