C++ 写入二进制文件字节错乱来源
C++ 写入二进制文件字节错乱来源
问题背景:利用OpenCV对图片进行处理后,为了将图片进行网络传输,需要将图片加载至内存中传输。
imread
不能满足此场景,此处使用imencode
函数。在将imencode
函数返回
的vector<uchar>
按字节序写入本地时,出现图片错乱的问题。
调试过程
根据写入文件的vector<uchar>
的size
值,可以发现文件大小要比size
的
值大几个字节。初步将问题定位于二进制文件读写出错。
Debug:先写一段读写二进制文件的小程序用于调试。代码如下:
#include <fstream>
using namespace std;
int main()
{
//定义一个待写入的uchar数组,大小为17
unsigned char tmpdata[17];
//初始化数组
for (size_t i = 0; i < 17; i++)
{
tmpdata[i] = i;
}
//打开待写入的文件
std::ofstream ofs("1.jpeg");
//每次写入一个字节
for (size_t i = 0; i < 17; i++)
{
ofs << tmpdata[i];
}
ofs.close();
}
上述代码执行后得到如下结果:
从上图可以看出,在内存地址为00000010
处,应该填充0A
此处却填充
为0D
,导致文件大小为18个字节,与预期不符。
问题成因:0x0A与0x0D分别对应的字符为\n和\r,我们遇到的问题是Windows系统换行为\r\n 导致的,当我们写入0x0A时,系统自动为我们添加上了0x0D,因此上述OpenCV写入图片乱码也同样由于 此问题导致。错误的写入文件方式是导致问题的根源。
解决方案
以二进制模式读写文件,系统就不会自动将0x0A替换为0x0D和0x0A。
关键代码:
std::ofstream ofs("1.jpeg",ios::binary);
在添加ios::binary
模式后,程序执行与预期相符。
附程序源码:
bool writeVectorToBin(const std::vector<uchar>& img_vec)
{
std::ofstream ofs("1.jpeg",ios::binary);
string str_encode(img_vec.begin(), img_vec.end());
ofs << str_encode;
ofs.flush();
ofs.close();
return true;
}