无法将特定内容写入stringstream?附二进制文件读取示例代码
解决二进制数据写入
std::stringstream的问题 我看了你的代码,能发现几个关键问题导致你无法把二进制内容正确写入std::stringstream,我来帮你逐一排查并修正:
1. 不完整的std::stringstream初始化
你代码里的初始化语句new std::stringstream("", std::ios_base::app | s...是不完整的,而且处理二进制数据时必须显式指定二进制模式——默认的文本模式会自动转换换行符等特殊字符,直接破坏二进制数据的完整性。正确的初始化应该是:
raw_data_buffer = new std::stringstream(std::ios_base::out | std::ios_base::binary | std::ios_base::app);
2. 缺失写入stringstream的核心步骤
你已经从文件把数据读到了buf里,但根本没把buf的内容写入raw_data_buffer!这是最关键的遗漏,需要添加write操作:
raw_data_buffer->write(buf, 40);
3. 未做文件打开失败的检查
如果1.raw不存在、权限不足或者路径错误,文件打开会直接失败,后续的read操作只会得到无效的垃圾数据。一定要先校验文件状态:
is.open("1.raw", std::ios::binary); if (!is.is_open()) { fprintf(stderr, "无法打开文件1.raw\n"); free(buf); return EXIT_FAILURE; }
4. 内存泄漏与不安全的内存分配
你用malloc分配的buf没有释放,会造成内存泄漏。对于固定大小的缓冲区,用栈上数组或者智能指针更安全省心:
// 推荐用栈上数组,自动释放无需手动管理 char buf[40]; // 或者用智能指针(适合动态大小场景) std::unique_ptr<char[]> buf(new char[40]);
5. 全局动态stringstream的隐患
全局的std::stringstream*指针不仅容易忘记释放,也不符合C++的最佳实践。建议改用局部对象,或者记得在程序结束前手动释放:
// 程序末尾释放指针,避免内存泄漏 delete raw_data_buffer;
修正后的完整代码
#include <sstream> #include <cstdio> #include <fstream> #include <cstdlib> #include <memory> // 用于std::unique_ptr int main() { std::ifstream is; is.open("1.raw", std::ios::binary); if (!is.is_open()) { fprintf(stderr, "无法打开文件1.raw\n"); return EXIT_FAILURE; } // 用智能指针管理缓冲区,自动释放 std::unique_ptr<char[]> buf(new char[40]); // 读取数据并检查是否成功 is.read(buf.get(), 40); if (!is) { fprintf(stderr, "读取文件失败,实际读取了%d字节\n", static_cast<int>(is.gcount())); } // 打印读取的十六进制内容(转成unsigned char避免负数补码问题) for (int i = 0; i < 40; i++) { printf("%02X ", static_cast<unsigned char>(buf[i])); } printf("\n"); // 初始化二进制模式的stringstream std::stringstream raw_data_buffer(std::ios_base::out | std::ios_base::binary); // 将二进制数据写入stringstream raw_data_buffer.write(buf.get(), 40); // 验证写入结果:导出stringstream内容并打印 std::string data_str = raw_data_buffer.str(); printf("stringstream中的内容(十六进制):\n"); for (unsigned char c : data_str) { printf("%02X ", c); } printf("\n"); return EXIT_SUCCESS; }
额外提示
- 打印
char类型的十六进制时,一定要转成unsigned char,否则负数会被当成补码打印(比如0xFF会显示为FFFFFFFF)。 - 如果文件大小小于40字节,
is.read()会读到文件末尾,此时可以用is.gcount()获取实际读取的字节数,避免处理无效数据。 - 尽量避免使用全局动态分配的对象,局部对象在作用域结束时会自动销毁,更安全可靠。
内容的提问来源于stack exchange,提问作者JACK M
相关产品推荐
相关产品推荐

