从python的str字节序列中获取unicode

时间:2018-03-07 06:03:26

标签: python ruby-on-rails ruby utf-8 character-encoding

我有一个旧的django应用程序,它在数据库中保存了UTF-8字符串,当我尝试在Ruby中获取它们时,它们看起来像无效的utf8。

保存前的字符串在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字符串?

1 个答案:

答案 0 :(得分:2)

我无法解决您的问题,但我可以解释该字节序列。你拥有的是UTF-8编码的UTF-16。

237, 160, 189237, 180, 165都是3字节的UTF-8序列:

  • 1110xxxx 10xxxxxx 10xxxxxxx&#39}是相关位)

...分别转换为代码点5535756613 :(或{16}中的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')
#=> ""