【问题标题】:Invalid UTF-8 Ruby strings无效的 UTF-8 Ruby 字符串
【发布时间】:2023-03-23 18:03:01
【问题描述】:

在 Ruby (v2.5.3) 处理编码字符串与 YAML 解析器的方式上,我遇到了一些奇怪的行为和不一致。这是一个例子:

"\x80"          # Returns "\x80"
"\x80".bytesize # Returns 1
"\x80".bytes    # Returns [128]
"\x80".encoding # Returns UTF-8

YAML.load('{value: "\x80"}')["value"]          # Returns "\u0080"
YAML.load('{value: "\x80"}')["value"].bytesize # Returns 2
YAML.load('{value: "\x80"}')["value"].bytes    # Returns [194, 128]
YAML.load('{value: "\x80"}')["value"].encoding # Returns UTF-8

我对 UTF-8 的理解是任何高于0x7F 的单字节值都应该被编码成两个字节。所以我的问题如下:

  1. 单字节字符串"\x80" 是有效的UTF-8 吗?
  2. 如果是这样,为什么 YAML 会转换为两字节模式?
  3. 如果不是,为什么 Ruby 声称编码是 UTF-8 但包含无效的字节序列?
  4. 有没有办法使 YAML 解析器和 Ruby 字符串的行为方式彼此相同?

【问题讨论】:

  • "\x80".valid_encoding? 绝对无效。不确定 YAML 在做什么
  • 好点——我认为当你尝试设置它时它会抛出错误或其他东西,但我猜它只是允许字符串并说如果你检查它是无效的。

标签: ruby


【解决方案1】:

不是有效的 UTF-8

"\x80".valid_encoding?
# false

Ruby 声称它是 UTF-8,因为默认情况下所有字符串文字都是 UTF-8,即使这会使它们无效。

我认为您不能强制 YAML 解析器返回无效的 UTF-8。但是要让 Ruby 转换该字符,您可以这样做

"\x80".b.ord.chr('utf-8')
# "\u0080"

.b 仅在 Ruby 2+ 中可用。否则你需要使用force_encoding

【讨论】:

    猜你喜欢
    • 2013-04-07
    • 1970-01-01
    • 2011-07-25
    • 1970-01-01
    • 2011-04-22
    • 2016-11-08
    • 1970-01-01
    • 2013-12-22
    • 2010-11-28
    相关资源
    最近更新 更多