Ruby 一个字符编码问题

Niatruc · 2017年04月19日 · 最后由 Niatruc 回复于 2017年04月19日 · 1526 次阅读

假设 a 是一个“ASCII-8BIT”编码的字符串变量,u 是一个“UTF-8”编码的字符串变量(但是其中包含\x**这样的字符),a+u 就会报”编码不兼容”的错误。

a = [192,168,1,100].pack("C*")
p a.encoding  #=> #<Encoding:ASCII-8BIT>

u = "\xff\xff\xff\xff\xff\xff"
p u.encoding #=> #<Encoding:UTF-8>

a+u  #=> Encoding::CompatibilityError: incompatible character encodings: ASCII-8BIT and UTF-8

看来也许\x**这样的字符是只有一个字节的,遇到两个字节作一个字符的 UTF-8 编码就会出问题。 ……但是 ruby 这个报错信息很模糊啊,让人一直误以为出错是因为这两种编码的字符串是不能做连接运算的(其实可以!!)。

这两种编码的字符串只能部分情况做连接运算,就是当它们是兼容的时候,比如 UTF-8 和 ASCII-8 对 ASCII 是兼容的(英文字母,数字,控制字符)等,是可以连接的,如果不兼容的时候是不能连接的。

\x**是直接存 2 进制,因为 utf 至少需要 1 位来标志字节数,所以超过 0x7f 就需要两个字节来存不能直接和 ascii-8 编码的相加

加之前会检查一下是否兼容 https://github.com/ruby/ruby/blob/cc68af3d026a3ece1dd890fd3510ed9c26660bc6/string.c#L1809

nowherekai 回复

原来如此,原来我理解得还不透彻……

adamshen 回复

感谢这么清晰的解答~

需要 登录 后方可回复, 如果你还没有账号请 注册新账号