Ruby 将字符串(表示UTF-8十六进制)转换为字符串

Ruby 将字符串(表示UTF-8十六进制)转换为字符串,ruby,utf-8,string-decoding,Ruby,Utf 8,String Decoding,我有一个UTF-8十六进制字符串,如下所示: s = "0059006F007500720020006300720065006400690074002000680061007300200067006F006E0065002000620065006C006F00770020003500200064006F006C006C006100720073002E00200049006600200079006F00750020006800610076006500200061006E00200041006400

我有一个UTF-8十六进制字符串,如下所示:

s = "0059006F007500720020006300720065006400690074002000680061007300200067006F006E0065002000620065006C006F00770020003500200064006F006C006C006100720073002E00200049006600200079006F00750020006800610076006500200061006E0020004100640064002D004F006E0020006F007200200042006F006E0075007300200079006F007500720020007200650073006F00750072006300650073002000770069006C006C00200077006F0072006B00200075006E00740069006C0020006500780068006100750073007400650064002E00200054006F00200074006F00700020007500700020006E006F007700200076006900730069007400200076006F006400610066006F006E0065002E0063006F002E006E007A002F0074006F007000750070"
我想把它转换成实际的UTF-8字符串。应改为:

你的信用额度已低于5美元。如果您有附加或奖金,您的资源将一直工作到耗尽。要立即添加,请访问vodafone.co.nz/toup

这项工作:

s.scan(/.{4}/).map { |a| [a.hex].pack('U') }.join

但是我想知道是否有更好的方法来实现这一点:我是否应该使用。

我认为字符串中有多余的空字符(这是有效的,但很浪费),但是您可以尝试:

[s].pack('H*').force_encoding('utf-8')
尽管如此,似乎“你的信用卡已低于5美元”


字符串打印时使用
puts
,但在转储字符串时,我无法读取终端上的所有unicode字符。

我认为字符串中有多余的空字符(这是有效的,但很浪费),但您可以尝试:

[s].pack('H*').force_encoding('utf-8')
尽管如此,似乎“你的信用卡已低于5美元”


字符串打印时使用
puts
,但在转储字符串时,我无法读取终端上的所有unicode字符。

如果您打算在其他奇怪编码的字符串上使用此选项,可以取消对前导字节的加载:

[s.gsub(/..(..)/,'\1')].pack('H*')
或者使用它们:

s.gsub(/..../){|p|p.hex.chr}

如果要使用Encoding::Converter

ec = Encoding::Converter.new('UTF-16BE','UTF-8')     # save converter for reuse
ec.convert( [s].pack('H*') )                         # or:  ec.convert [s].pack'H*'

如果您打算在其他奇怪编码的字符串上使用此选项,则可以取消对前导字节的加载:

[s.gsub(/..(..)/,'\1')].pack('H*')
或者使用它们:

s.gsub(/..../){|p|p.hex.chr}

如果要使用Encoding::Converter

ec = Encoding::Converter.new('UTF-16BE','UTF-8')     # save converter for reuse
ec.convert( [s].pack('H*') )                         # or:  ec.convert [s].pack'H*'

额外的
00
s表明字符串实际上是字符串的十六进制表示,而不是UTF-8。假设在这种情况下,获取UTF-8字符串需要执行的步骤是:首先将字符串转换为十六进制数字表示的实际字节(可用于此),然后将其标记为使用适当的编码(看起来像UTF-16BE),最后使用将其转换为UTF-8:

[s].pack('H*').force_encoding('utf-16be').encode('utf-8')

额外的
00
s表明字符串实际上是字符串的十六进制表示,而不是UTF-8。假设在这种情况下,获取UTF-8字符串需要执行的步骤是:首先将字符串转换为十六进制数字表示的实际字节(可用于此),然后将其标记为使用适当的编码(看起来像UTF-16BE),最后使用将其转换为UTF-8:

[s].pack('H*').force_encoding('utf-16be').encode('utf-8')

我认为这不是UTF-8,因为
00
是一个控制字符(NIL)。看起来更像某种16位编码。@CraigS.Anderson UTF-8不具备8位或16位的能力吗?@vol7ron UTF-8是一种可变长度编码。ASCII字符(0-127)映射到一个字节,其他字符更长-最多6个字节。如果前导位是0,那么它是代码点的单字节编码。我认为这不是UTF-8,因为
00
是一个控制字符(NIL)。看起来更像某种16位编码。@CraigS.Anderson UTF-8不具备8位或16位的能力吗?@vol7ron UTF-8是一种可变长度编码。ASCII字符(0-127)映射到一个字节,其他字符更长-最多6个字节。如果前导位为0,则它是代码点的单字节编码。它不是UTF-8,因此强制编码为UTF-8是不正确的。@CraigS.Anderson:它是UTF-8,并且编码有效-请检查
[s]。pack('H*')。force_编码('UTF-8')。valid_编码?
。。。另外,您可以使用
encode
而不是
force_编码
,例如:
[s].pack('H*').encode('utf-8')
-但是如果编码有效,为什么要浪费资源呢?'Yo'的utf-8编码是0x596F,而不是0x0059006F。@CraigS.Anderson,答案仍然回答了这个问题-即使字符串格式不正确。我不确定,但我认为您可以在127以下的值的开头添加null,因此Y变为0x0059,o变为0x006F。事实上,字符串通过了验证并正确打印。我该和谁争论这台计算机?它不是UTF-8,所以强制编码为UTF-8是不正确的。@CraigS.Anderson:它是UTF-8,编码是有效的-检查
[s].pack('H*')。强制编码('UTF-8')。有效编码?
。。。另外,您可以使用
encode
而不是
force_编码
,例如:
[s].pack('H*').encode('utf-8')
-但是如果编码有效,为什么要浪费资源呢?'Yo'的utf-8编码是0x596F,而不是0x0059006F。@CraigS.Anderson,答案仍然回答了这个问题-即使字符串格式不正确。我不确定,但我认为您可以在127以下的值的开头添加null,因此Y变为0x0059,o变为0x006F。事实上,字符串通过了验证并正确打印。我是谁?如果你的字符串有一个相关的双零,比如
“s\n”
(==
200a
,十六进制)。。。?我不会删除那些双零。@Myst你是对的,这是不负责任的,我已经更新了答案:)如果你的字符串有一个相关的双零,比如
“s\n”
(==
200a
十六进制)。。。?我不会删除那些双零。@Myst你是对的,这是不负责任的,我已经更新了答案:)