如何在不修改第三方类A的前提下保留写入的"1111"内容?
问题分析与解决方案
问题原因
核心问题是多个文件流操作同一文件时的状态不同步:
- 类
A的构造函数打开文件后写入AAABBB,其内部的ofstream指针停在文件第6字节位置(0-based)。 - 你用
os2打开同一文件写入1111后关闭,但A内部的os1完全不知道文件内容和长度已变化,指针仍停在第6字节。 - 调用
a.write_more()时,os1从第6字节开始写入,直接覆盖了os2刚写入的1111,导致内容丢失。
可行解决方案(无需修改类A)
已知A构造函数写入的字节数(6字节),我们可以通过先备份被覆盖内容,再重新插入的方式保留1111,具体步骤如下:
- 关闭
os2后,读取文件中AAABBB之后的所有内容(即1111)并保存到内存。 - 调用
a.write_more(),让第三方库完成写入操作。 - 把备份的
1111插入到AAABBB和Appended more.之间,修复文件内容。
修改后的代码实现
#include <fstream> #include <string> #include <iostream> // 第三方类A,不可修改 class A { std::ofstream os1; public: A(std::string& str) { os1.open(str, std::ios::trunc); if (os1.bad()) { os1 << "Writing failed.." << std::endl; os1.close(); } os1 << "AAA"; os1 << "BBB"; } void write_more() { os1 << "Appended more."; } void close() { os1.close(); } }; void write_os1_os2_os1() { std::string str("temp/a.txt"); const size_t a_written_len = 6; // 已知A构造函数写入的字节数 A a(str); std::fstream os2(str, std::ios::in | std::ios::out); if (os2.bad()) { std::cerr << "Writing failed.." << std::endl; os2.close(); return; } os2.seekp(5); os2 << "1111"; os2.close(); // 保存os2写入的内容 std::string inserted_content; std::ifstream read_file(str); if (read_file.is_open()) { read_file.seekg(a_written_len); inserted_content.assign(std::istreambuf_iterator<char>(read_file), std::istreambuf_iterator<char>()); read_file.close(); } // 调用第三方库的write_more a.write_more(); a.close(); // 插入保存的内容,修复文件 std::string full_content; std::ifstream read_final(str); if (read_final.is_open()) { full_content.assign(std::istreambuf_iterator<char>(read_final), std::istreambuf_iterator<char>()); read_final.close(); // 在AAABBB之后插入1111 full_content.insert(a_written_len, inserted_content); std::ofstream write_final(str, std::ios::trunc); if (write_final.is_open()) { write_final << full_content; write_final.close(); } } } int main() { write_os1_os2_os1(); return 0; }
原理说明
- 核心思路是绕开
A内部文件流的状态问题:既然无法修改A的代码同步文件指针,就先备份需要保留的内容,等A完成写入后再把备份内容插回正确位置。 - 该方法完全依赖已知的
A构造函数写入字节数,不需要访问A的私有成员,也不会破坏第三方库的逻辑。
风险提示:不推荐的技巧
有人可能会尝试通过指针偏移强制访问A的私有os1成员,调用seekp(std::ios::end)同步文件指针。但这种方法依赖编译器的内存布局,属于C++标准中的未定义行为,不同编译器、编译选项下都可能出错,绝对不建议在生产环境使用。
内容的提问来源于stack exchange,提问作者qqqqq
相关产品推荐
相关产品推荐

