Base64编码是将任意二进制数据按3字节分组映射为4个ASCII字符的可打印字符串转换,非加密且不处理字符编码;C++需手写实现,核心为查表、补零与填等号,并注意std::string存储二进制时用.size()而非strlen()。

Base64 编码的本质是字节流到 ASCII 字符串的映射
Base64 不是加密,也不处理字符串编码(如 UTF-8/GBK),它只把任意 std::vector 或 const uint8_t* 二进制数据,按每 3 字节分组,映射为 4 个可打印 ASCII 字符。C++ 中没有标准库函数直接支持,必须自己实现或依赖第三方,但实现本身很轻量——核心就是查表 + 补零 + 填等号。
手写 Base64 编码函数:避开 std::string 的隐式编码陷阱
常见错误是先用 std::string 存二进制数据(比如从文件读、网络接收),再传给编码函数——这本身没问题,但要注意:std::string 在 C++11 后可安全存任意字节(包括 \0),但若误用 .c_str() 或 .data() 后接 strlen(),会提前截断。编码函数必须用 .size() 获取真实字节数。
- 查表用
static constexpr char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" - 输入长度为
n,输出长度固定为((n + 2) / 3) * 4(向上取整到 4 的倍数) - 每 3 字节(
a,b,c)拆成 4 组 6 位:(a>>2), ((a&3)>4), ((b&15)>6), c&63 - 不足 3 字节时,用
0填充,并在末尾补=:1 字节输 2 个=,2 字节输 1 个=
std::string base64_encode(const std::vector& input) { static constexpr char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; std::string out; size_t n = input.size(); out.reserve(((n + 2) / 3) * 4); for (size_t i = 0; i < n; i += 3) { uint32_t val = (input[i] << 16); if (i + 1 < n) val |= (input[i + 1] << 8); if (i + 2 < n) val |= input[i + 2]; out.push_back(table[(val >> 18) & 63]); out.push_back(table[(val >> 12) & 63]); out.push_back(i + 1 < n ? table[(val >> 6) & 63] : '='); out.push_back(i + 2 < n ? table[val & 63] : '='); } return out;}
处理 UTF-8 字符串时:先转字节,再编码
如果你有一个含中文的
std::string(假设它是 UTF-8 编码),想 Base64 它,**不要**尝试“逐字符编码”或用wstring。UTF-8 已经是字节序列,直接传给上面的函数即可:立即学习“C++免费学习笔记(深入)”;
std::string utf8_str = u8"你好 world"; std::string b64 = base64_encode(std::vector(utf8_str.begin(), utf8_str.end())); // 输出:5L2g5aW9IHdvcmxk 反过来解码后,得到的仍是原始 UTF-8 字节流,可直接构造
std::string并按 UTF-8 解释——C++ 不管编码语义,只管字节。注意平台差异和边界情况
Windows 下若从文件读二进制,务必用
std::ios::binary打开,否则换行符会被悄悄转换;Linux/macOS 虽不转换,但统一用 binary 模式更安全。另外,空输入(size()==0)应返回空字符串,不是"=="或崩溃——上面实现已覆盖该情况。真正容易被忽略的是:Base64 输出字符串里不含换行或空格,如果协议要求每 76 字符折行(如 MIME),那是上层封装逻辑,不是 Base64 编码本身的责任。











