【问题标题】:Ruby 1.9.3 Why does "\x03".force_encoding("UTF-8") get \u0003 ,but "\x03".force_encoding("UTF-16") gets "\x03"Ruby 1.9.3 为什么 "\x03".force_encoding("UTF-8") 得到 \u0003 ,但 "\x03".force_encoding("UTF-16") 得到 "\x03"
【发布时间】:2014-04-17 13:09:33
【问题描述】:

Ruby 1.9.3

irb(main):036:0* "\x03".force_encoding("UTF-16")
=> "\x03"
irb(main):040:0* "\x03".force_encoding("UTF-8")
=> "\u0003"

为什么 "\x03".force_encoding("UTF-8") 是 \u0003 而 "\x03".force_encoding("UTF-16") 以 "\x03" 结尾,我认为应该是另一个绕路?

【问题讨论】:

  • 请不要对我投反对票,如果我做出错误的假设,请赐教。谢谢。
  • "\x03".force_encoding('binary').encode('utf-16') 可能更有启发性。 force_encoding 允许您生成无效编码的文本,例如 \x03 伪装成 UTF-16 或 "\xce".force_encoding('utf-8') 伪装成 UTF-8。我的 UTF-16 知识相当稀少,所以只是评论。
  • 你能解释一下为什么我不能将 "\x81" 与 [993].pack("n") 连接,但我可以在 [993] 时使用 "\x81" 和 "\x03\xE1" ].pack("n") 是 "\x03\xE1"。

标签: ruby-on-rails ruby encoding utf-8 utf-16


【解决方案1】:

因为"\x03" 不是 UTF-16 中的有效代码点,而是 UTF-8 中的有效代码点(ASCII 03、ETX、文本结尾)。您必须使用至少两个字节来表示 UTF-16 中的 unicode 代码点。

这就是为什么 "\x03" 在 UTF-8 中可以被视为 unicode \u0003 而在 UTF-16 中却不能。

要在 UTF-16 中表示 "\u0003",您必须使用两个字节,00 0303 00,具体取决于字节顺序。这就是为什么我们需要在 UTF-16 中指定字节顺序。对于big-endian版本,字节序列应该是

FE FF 00 03

对于little-endian,字节序列应该是

FF FE 03 00

字节顺序标记应出现在字符串的开头,或文件的开头。

从 Ruby 1.9 开始,String 只是一个以特定编码作为标记的字节序列。 force_encoding 是一种改变编码标签的方法,它不会影响字节序列。您可以通过检查 "\x03".force_encoding("UTF-8").bytes 来验证这一点。

如果你看到"\u0003",这并不意味着你得到了一个用两个字节表示的字符串00 03,而是一些表示Unicode代码点0003的字节在特定的该字符串中携带的编码。可能是:

03              //tagged as UTF-8
FE FF 00 03     //tagged as UTF-16
FF FE 03 00     //tagged as UTF-16
03              //tagged as GBK
03              //tagged as ASCII
00 00 FE FF 00 00 00 03 // tagged as UTF-32
FF FE 00 00 03 00 00 00 // tagged as UTF-32

【讨论】:

  • 如果 "\x03" 在 UTF-16 中无效,为什么要强制它为 UTF-16 你会得到 "\x03" 而不是 "\u0003" ?
  • 在case2中,显然\x03是一个字节的东西,并且强制它是utf-8,我最终得到了一个2字节的东西???我还是不明白。
  • @tensaix2j 从 Ruby 1.9 开始,String 只是一个带有特定编码作为标记的字节序列。 force_encoding 是一种改变编码标签的方法,它不会影响字节序列。您可以通过检查 "\x03".force_encoding("UTF-8").bytes 来验证这一点。
  • "\x81" + [993].pack("n") Encoding::CompatibilityError: incompatible character encodings: IBM437 and ASCII-8BIT from (irb):70 from c:/ruby/2.0 .0/bin/irb:12:in <main>' irb(main):071:0> [993].pack("n") => "\x03\xE1" irb(main):072:0> irb(main):073:0* "\x81" + "\x03\xE1" => "\x81\x03\xE1" irb(main):074:0> "\x81" + [993].pack("n").b Encoding::CompatibilityError: incompatible character encodings: IBM437 and ASCII-8BIT from (irb):74 from c:/ruby/2.0.0/bin/irb:12:in
    '
  • @tensaix2j 错误信息已经告诉你了。在您的机器中,"\x81" 是带有编码标签IBM437[129],而[993].pack("n") 为您提供带有编码标签ASCII-8BIT[3, 225]。当底层编码标签相同时,您只能连接两个字符串。在这种情况下,你可以做"\x81".force_encoding("ASCII-8BIT") + [993].pack("n")
猜你喜欢
  • 2012-04-29
  • 1970-01-01
  • 2021-01-30
  • 2011-01-11
  • 2012-08-18
  • 2021-01-06
  • 2018-11-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多