Boost gzip_compressor压缩流读写异常:读取uint64_t获坏字节
压缩数据读写异常问题分析
代码实现
以下是使用Boost.Iostreams实现的压缩数据保存与加载函数:
namespace io = boost::iostreams; void saveCompressedData(const std::string& file_path, const std::vector<double>& bid, const std::vector<double>& ask, const std::vector<double>& close_prices, const std::vector<int>& tick_numbers) { try { // Create an output file stream and filtering stream std::ofstream file(file_path, std::ios_base::out | std::ios_base::binary); if (!file) { std::cerr << "Error opening compressed file for writing: " << file_path << std::endl; return; } io::filtering_ostream out; out.push(io::gzip_compressor()); out.push(file); // Write the data to the compressed file uint64_t size = bid.size(); out.write((const char* ) (&size), sizeof(size)); out.write(reinterpret_cast<const char*>(bid.data()), size * sizeof(double)); out.write(reinterpret_cast<const char*>(ask.data()), size * sizeof(double)); size_t close_size = close_prices.size(); out.write(reinterpret_cast<const char*>(&close_size), sizeof(close_size)); out.write(reinterpret_cast<const char*>(close_prices.data()), close_size * sizeof(double)); size_t tick_size = tick_numbers.size(); out.write(reinterpret_cast<const char*>(&tick_size), sizeof(tick_size)); out.write(reinterpret_cast<const char*>(tick_numbers.data()), tick_size * sizeof(int)); out.pop(); } catch (const std::exception& e) { std::cerr << "Exception while writing compressed data: " << e.what() << std::endl; } } void loadCompressedData(const std::string& file_path, std::vector<double>& bid, std::vector<double>& ask, std::vector<double>& close_prices, std::vector<int>& tick_numbers) { try { // Create an input file stream and filtering stream std::ifstream file(file_path, std::ios_base::in | std::ios_base::binary); if (!file) { std::cerr << "Error opening compressed file for reading: " << file_path << std::endl; return; } io::filtering_istream in; in.push(io::gzip_decompressor()); in.push(file); // Read the data from the compressed file uint64_t size; in.read((char*)(&size), sizeof(size)); bid.resize(size); ask.resize(size); in.read(reinterpret_cast<char*>(bid.data()), size * sizeof(double)); in.read(reinterpret_cast<char*>(ask.data()), size * sizeof(double)); size_t close_size; in.read(reinterpret_cast<char*>(&close_size), sizeof(close_size)); close_prices.resize(close_size); in.read(reinterpret_cast<char*>(close_prices.data()), close_size * sizeof(double)); size_t tick_size; in.read(reinterpret_cast<char*>(&tick_size), sizeof(tick_size)); tick_numbers.resize(tick_size); in.read(reinterpret_cast<char*>(tick_numbers.data()), tick_size * sizeof(int)); } catch (const std::exception& e) { std::cerr << "Exception while reading compressed data: " << e.what() << std::endl; } }
问题描述
测试上述代码时,在loadCompressedData函数中读取uint64_t类型的size变量时获取到错误字节,请问可能的原因是什么?
可能的原因分析
- 字节序(端序)不匹配:直接将内存中的二进制数据写入文件时,不同CPU架构的字节序(小端/大端)会导致数值解析错误。比如在x86(小端)机器写入的
uint64_t数据,在大端架构的机器上读取时,字节顺序会被反转,得到完全错误的数值。 - 流未正确刷新导致写入不完整:
saveCompressedData中仅调用out.pop(),可能未确保gzip压缩器的内部缓冲完全写入文件。如果压缩器还有未刷新的数据,会导致文件开头的size字段不完整或缺失,读取时自然得到错误字节。 - 文件损坏或写入中断:写入过程中若出现磁盘空间不足、程序意外退出、文件被截断等情况,会导致文件数据不完整,读取时无法正确解析开头的
size字段。 - 类型大小的平台差异:代码中
bid的大小用uint64_t写入,但close_size、tick_size用size_t写入。size_t的大小随平台变化(32位系统为4字节,64位为8字节),若写入和读取的平台size_t大小不同,会导致后续数据偏移,进而破坏整个文件的结构,连带着开头的size读取也出现错误。 - 二进制模式未生效:虽然代码中指定了
std::ios_base::binary打开文件,但在Windows等平台上,若编译时出现错误或代码被意外修改,导致文件以文本模式打开,会自动转换换行符,破坏二进制数据的字节结构,引发读取错误。
内容的提问来源于stack exchange,提问作者Aftershock
相关产品推荐
相关产品推荐

