求助:实现JPG转Base64的C++方案(适配PLC与Web传输)
问题分析与解决方案
你的问题核心有两个:一是二进制文件读取方式错误,二是缺少Base64编码步骤——直接输出二进制字节当然会显示乱码,Base64是把二进制数据转换成ASCII字符集的编码格式,需要专门的编码逻辑。
为什么你的代码失败?
getline是为文本文件设计的,它会在遇到\n或\0时停止读取,而二进制图片文件里充满了这类控制字符,导致你读取的内容不完整,甚至提前中断。- 你只是把读取到的二进制字节直接写入文本文件,这些字节大多是非ASCII字符,自然显示成乱码,完全没有做Base64编码转换。
正确的实现步骤
1. 完整读取二进制图片文件
用ifstream的read方法一次性读取所有字节到缓冲区(比如std::vector<unsigned char>),避免文本读取函数的截断问题。
2. 实现Base64编码
C++标准库没有内置Base64编码器,所以我们需要自己实现一个简单版本。Base64的编码规则是:
- 将每3个字节(24位)拆分成4个6位的片段
- 每个6位片段对应Base64编码表中的一个字符
- 如果最后剩余1个字节,补两个
=;剩余2个字节,补一个=
完整代码示例
#include <iostream> #include <fstream> #include <vector> #include <string> // Base64编码表 const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; // 二进制数据转Base64字符串 std::string base64_encode(const unsigned char* bytes_to_encode, unsigned int in_len) { std::string ret; int i = 0; int j = 0; unsigned char char_array_3[3]; unsigned char char_array_4[4]; while (in_len--) { char_array_3[i++] = *(bytes_to_encode++); if (i == 3) { char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; for(i = 0; (i <4) ; i++) ret += base64_chars[char_array_4[i]]; i = 0; } } if (i) { for(j = i; j < 3; j++) char_array_3[j] = '\0'; char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; for (j = 0; (j < i + 1); j++) ret += base64_chars[char_array_4[j]]; while((i++ < 3)) ret += '='; } return ret; } int main() { // 1. 读取二进制图片文件 std::ifstream input("test.jpg", std::ios::binary | std::ios::ate); if (!input.is_open()) { std::cerr << "无法打开图片文件!" << std::endl; return 1; } // 获取文件大小,分配缓冲区 std::streampos file_size = input.tellg(); std::vector<unsigned char> image_data(file_size); // 回到文件开头,读取全部内容 input.seekg(0, std::ios::beg); input.read(reinterpret_cast<char*>(image_data.data()), file_size); input.close(); // 2. 进行Base64编码 std::string base64_str = base64_encode(image_data.data(), image_data.size()); // 3. 写入到文本文件 std::ofstream output("text.txt"); if (output.is_open()) { output << base64_str; output.close(); std::cout << "Base64编码完成,已写入text.txt" << std::endl; } else { std::cerr << "无法打开输出文件!" << std::endl; return 1; } return 0; }
额外注意事项
- 你的Web端代码里写的是
data:image/png;base64,,但你处理的是JPG图片,应该改成data:image/jpeg;base64,,否则Web应用可能无法正确解析显示图片。 - 如果PLC对传输的字符串长度有要求,你可能需要考虑分块传输Base64字符串,或者压缩图片后再编码(不过JPG本身已经是压缩格式,压缩空间不大)。
内容的提问来源于stack exchange,提问作者EterNaL_SC2
相关产品推荐
相关产品推荐

