从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, 189237, 180, 165都是3字节的UTF-8序列:

  • 1110xxxx 10xxxxxx 10xxxxxxx是相关位)

…分别转换为代码点5535756613 :(或hex的0xD83D0xDD25

 [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') #=> "🔥"