我们知道,在base64.StdEncoding
或base64.RawStdEncoding
中有两种解码base64字符串的方法。如何使用其中一个正确解码一个base64字符串?如果调用了不正确的编码方法。例如,如果使用RawStdEncoding
解码一个StdEncoding
字符串,则会出现illegal base64 data at input byte xxx
错误。
每个医生
const (
StdPadding rune = '=' // Standard padding character
NoPadding rune = -1 // No padding
)
RawStdEncoding是标准的原始的,未填充的base64编码,在RFC 4648章节3.2中定义。这与StdEncoding相同,但省略了填充字符。
我们应该通过检查填充结束是否为StdPadding
来区分它们吗?代码片段
lastByte := s[len(s)-1:]
if lastByte == string(base64.StdPadding) {
base64.StdEncoding.DecodeString(s)
} else {
base64.RawStdEncoding.DecodeString(s)
}
这是一种优雅的方式吗?或者我错过了什么?解码base64字符串的优雅方式是什么?
更新:
可能有一种原始的方法是通过错误检查,如下所示
rawByte, err := base64.StdEncoding.DecodeString(s)
if err != nil {
rawByte, err = base64.RawStdEncoding.DecodeString(s)
}
我们知道,在围棋中有两种解码base64字符串的方法base64。
还有base64。使用字符-
和_
代替url不安全的base64字符+
和/
的URLEncoding。
我们应该通过检查填充的结束来区分它们吗stdp加不加?代码片段
这行不通。有1/3的几率base64编码没有可见的填充:
b := []byte("abc123") // len(b) % 3 == 0 - no padding
fmt.Println(base64.StdEncoding.EncodeToString(b)) // YWJjMTIz
fmt.Println(base64.RawStdEncoding.EncodeToString(b)) // YWJjMTIz
https://play.golang.org/p/LMtIHlyXdn7
那么如何区分它们-并确定使用了哪种编码?
是的,你可以像你更新的问题一样双重解码:
rawByte, err := base64.StdEncoding.DecodeString(s)
if err != nil {
rawByte, err = base64.RawStdEncoding.DecodeString(s)
}
你可以使用一些技巧来做出一些有根据的猜测。例如:
e := base64.StdEncoding.EncodeToString(b) // always produces a mutiple of 4 length
if len(e) % 4 != 0 {
// cannot be base64.StdEncoding - so try base64.RawStdEncoding?
}
如果您获得illegal base64 data at input byte ...
则:
- 您使用了错误的base64解码器,或者
- 在调用解码器之前,base64字符串之后必须剥离更多数据,或者
- 输入不是base64。
我们应该通过检查填充结束是否为StdPadding来区分它们吗?
。就像你知道数据是base64编码的一样,你也应该知道是如何编码的,并使用base64.StdEncoding
或base64.RawStdEncoding
,不是两者都有。您不需要猜测这些事情,而只需使用与发送方使用的编码相对应的decode方法。
Base64编码可以不同:
- 填充/未填充(末尾没有
=
s) - 标准(
+
,/
)或URL (-
,_
)字母 - 带/不带换行符(例如MIME以76个字符分隔行,PEM以64个字符分隔行)
您可以直观地检查编码字符串以猜测编码方案。但请注意,填充并不总是存在-它取决于源数据的长度是否为3的倍数,因为每个3字节的元组被编码为4个6位字符。