Go语言base64流式编码在收尾时的一个小坑

问题复现

请看下面代码

sb := strings.Builder{}
_, err := io.Copy(
	base64.NewEncoder(base64.StdEncoding, &sb),
	bytes.NewBufferString("12345678"),
)
if err != nil {
	panic(err)
}
fmt.Println("编码后:", sb.String())
data, err := base64.StdEncoding.DecodeString(sb.String())
if err != nil {
	panic(err)
}
fmt.Println("解码后:", string(data))

这里利用io.Copy将任意io.Reader编码为base64字符串,这种写法在处理网络通信等流式数据时十分简洁高效。可是,以上代码运行结果如下:

编码后: MTIzNDU2
解码后: 123456

显见,末尾的78被丢掉了。

原因分析

base64结尾处使用===标记编码未满,因此流式编码器在不知道当前是否为文件末尾时,不会贸然写入===,而是统一以3字节组进行编码,将不满3字节的写入数据残余部分先暂存起来。
  这样做是因为每3字节原始数据正好对应4字节base64编码,而完整的base64编码并不包含===,因此可以直接写入接收端。
  为了适配流式编码,base64.NewEncoder返回的并不是io.Writer而是io.WriteCloser。我们必须要显式调用其Close方法以通知编码器写入结尾残余部分,否则当原始数据长度不是3的倍数时,将在结尾处出现结尾缺损。

解决方案

编码结束后调用流式编码器的Close方法。

sb := strings.Builder{}
enc := base64.NewEncoder(base64.StdEncoding, &sb)
_, err := io.Copy(
	enc,
	bytes.NewBufferString("12345678"),
)
if err != nil {
	panic(err)
}
err = enc.Close()
if err != nil {
	panic(err)
}
fmt.Println("编码后:", sb.String())
data, err := base64.StdEncoding.DecodeString(sb.String())
if err != nil {
	panic(err)
}
fmt.Println("解码后:", string(data))

此时,输出恢复正常。

编码后: MTIzNDU2Nzg=
解码后: 12345678

相关推荐

  1. Go语言base64编码收尾一个

    2024-03-27 10:22:11       18 阅读
  2. ssh运行base64编码命令

    2024-03-27 10:22:11       39 阅读
  3. 图片Base64编码

    2024-03-27 10:22:11       8 阅读
  4. phpUrl 安全base64编码解码类

    2024-03-27 10:22:11       33 阅读
  5. Base64 编码表 参考

    2024-03-27 10:22:11       7 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-27 10:22:11       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-27 10:22:11       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-27 10:22:11       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-27 10:22:11       20 阅读

热门阅读

  1. 正则表达式:深入理解与应用

    2024-03-27 10:22:11       16 阅读
  2. CentOS 7 安装 Git

    2024-03-27 10:22:11       20 阅读
  3. 11. Linux中进程控制细节

    2024-03-27 10:22:11       19 阅读
  4. 【算法】计数排序

    2024-03-27 10:22:11       17 阅读
  5. 算法打卡day18

    2024-03-27 10:22:11       18 阅读
  6. 握手和挥手

    2024-03-27 10:22:11       19 阅读
  7. npm常用命令详解

    2024-03-27 10:22:11       17 阅读
  8. Excel 导入、导出的封装

    2024-03-27 10:22:11       20 阅读
  9. 【go-工具】pprof

    2024-03-27 10:22:11       15 阅读