查看Ruby的Base64.encode的源代码在Base64中编码该数据之前,我无法确定将字符串转换为什么字符编码(如果有的话)。在Base64中编码的Utf-8字符串将与在Base64中编码的Utf-16字符串有很大不同。 Ruby是否会对此操作做出任何承诺?
答案 0 :(得分:28)
在base64中编码和解码utf-8字符串的示例:
text = "intérnalionálização"
=> "intérnalionálização"
text.encoding
=> #<Encoding:UTF-8>
encoded = Base64.encode64(text)
=> "aW50w6lybmFsaW9uw6FsaXphw6fDo28=\n"
encoded.encoding
=> #<Encoding:US-ASCII>
decoded = Base64.decode64(encode)
=> "int\xC3\xA9rnalion\xC3\xA1liza\xC3\xA7\xC3\xA3o"
decoded.encoding
=> #<Encoding:US-ASCII>
decoded = decoded.force_encoding('UTF-8')
=> "intérnalionálização"
decoded.encoding
=> #<Encoding:UTF-8>
答案 1 :(得分:10)
fine manual有这样说:
<强> encode64(bin)中强>
返回Base64编码的bin版本。此方法符合RFC 2045。
RFC 2045的第6.8节说:
<强> 6.8。 Base64 Content-Transfer-Encoding
Base64 Content-Transfer-Encoding旨在以不需要人类可读的形式表示任意八位字节序列。 [...]
使用65个字符的US-ASCII子集,每个可打印字符可以表示6位。 (额外的第65个字符“=”用于表示特殊处理功能。)
因此Base64将 bytes 编码为ASCII。如果这些字节实际上代表UTF-8编码的字符串,则UTF-8字符串将被分解为单个字节,并且这些字节将被转换为Base64;例如,如果您有一个UTF-8字符串'µ'
,那么您最终将字节0xc2
和0xb5
(按此顺序)编码为Base64表示"wrU=\n"
。如果您从二进制字符串"\xc2\xb5"
开始(恰好匹配'µ'
的UTF-8版本),那么您将得到相同的"wrU=\n"
输出。
当您解码"wrU=\n"
时,您将获得字节"\xc2\xb5"
,并且您必须知道这些字节应该是UTF-8编码的文本而不是某些任意blob的位。这就是为什么你有单独的内容类型和字符集元数据附加到Base64。
类似地,如果你有一个UTF-16字符串,那么它将被分成字节,这些字节将被编码,就像任何其他字节字符串一样。当然,由于字节顺序问题,这种情况稍微复杂一些,但这就是为什么我们有内容类型和字符集标题和BOM。
重点是Base64使用 bytes ,而不是字符。什么格式(UTF-8文本,UTF-16文本,PNG图像......)是别人的问题。 Base64只是将字节流转换为US ASCII的子集,然后再转换为字节;必须单独指定这些字节的格式。
我在源头做了一些探讨,结果可能会引起人们的兴趣,即使它们并不完全相关。 encode64
method就是这样:
def encode64(bin)
[bin].pack("m")
end
然后,如果你浏览Array#pack
:
static VALUE
pack_pack(VALUE ary, VALUE fmt)
{
/*...*/
int enc_info = 1; /* 0 - BINARY, 1 - US-ASCII, 2 - UTF-8 */
并密切关注enc_info
,您会看到'm'
格式会单独留下enc_info
,因此打包的字符串将以US-ASCII形式出现,因此{{1将按预期生成US ASCII输出。