从python的str字节序列中获取unicode
我有一个旧的django应用程序,它在数据库中保存了UTF-8字符串,当我尝试在Ruby中获取它们时,它们看起来像无效的utf8。
保存之前的str
在python中是str
类型,但是当从数据库中获取时,django给了我一个合适的unicode
字符串。 当我在rails中获取相同的记录时,我得到一个与python的str
字符串相同的字节序列,而ruby抱怨它是一个无效的字节序列。
示例:测试过的字符串是一个表情符号:🔥
-
在保存在Django-
str
类型之前,序列:[237, 160, 189, 237, 180, 165]
-
从Django中的db获取 –
unicode
类型,序列[55357, 56613]
-
从Rails中的db获取 – 序列
[237, 160, 189, 237, 180, 165]
有没有办法将Ruby中的字节序列转换为正确的utf8字符串?
我无法解决你的问题,但我可以解释那个字节序列。 你拥有的是UTF-8编码的UTF-16。
237, 160, 189
和237, 180, 165
都是3字节的UTF-8序列:
-
1110xxxx 10xxxxxx 10xxxxxx
(x
是相关位)
…分别转换为代码点55357
和56613
:(或hex的0xD83D
和0xDD25
)
[237, 160, 189, 237, 180, 165].map { |b| b.to_s(2) } #=> ["11101101", "10100000", "10111101", "11101101", "10110100", "10100101"] # ^^^^ ^^^^^^ ^^^^^^ ^^^^ ^^^^^^ ^^^^^^ [0b1101_100000_111101, 0b1101_110100_100101] #=> [55357, 56613]
不幸的是,这些代码点在UTF-8中无效 。 那是因为它们实际上是UTF-16字节:
[55357, 56613].pack('S>2').encode('utf-8', 'utf-16be') #=> "🔥"