【问题标题】:Fixing incorrectly encoded strings in Ruby修复 Ruby 中编码错误的字符串
【发布时间】:2023-03-30 22:20:01
【问题描述】:

背景

我的 Postgres 数据库中的数据在某些时候被错误地编码。

数据库采用 UTF-8 编码。有问题的表有一列包含 YAML 序列化数据。某些行包含似乎由它们的两字节 UTF 等效项表示的非 ascii 字符。更容易展示:

> puts data
#  ---
#  :method_name: new
#  :method_args:
#  - "M\xC3\xB6bler"
#  - ""
#  - false
#  - ""
#  - test
#  - f8685480-a36b-012f-54c1-1093e95ec0bb

> data.encoding
# => # <Encoding:UTF-8>

\xC3\xB6 应该是字符ö

您可以通过使用 unicode 字符串来获得相同的结果:

> string = "ö".force_encoding("ascii-8bit")
# => "\xC3\xB6"

但是,在这种情况下,原始字节被保留,因此我们可以转换回 UTF:

> string.force_encoding("utf-8")
# => "ö"

打印\xC3\xB6 似乎只是一种显示在 ASCII-8BIT 中没有意义的字节的方式。你可以通过调用.chars来说明这一点:

> string.chars
# => ["\xC3", "\xB6"]

但在来自数据库的字符串中,\xC3\xB6 实际上是八个字符。

> data[42..49].chars
# => ["\\", "x", "C", "3", "\\", "x", "B", "6"]

因此,您不能只强制使用 ASCII-8bit 并再次返回 - 这是我第一次尝试解决方案。

我的下一个想法是以某种方式恢复原始字节,但这比我想象的要难。

这里建议了一种可能的(hackish)解决方案:Best way to escape and unescape strings in Ruby?

那个解决方案对我不起作用,可能是因为字符串代表 YAML。

问题

如何恢复原来的unicode字符?

我想我可以写一个巨大的 gsub 表达式,但我宁愿避免这样做。

【问题讨论】:

    标签: ruby character-encoding


    【解决方案1】:

    我想我可以写一个巨大的 gsub 表达式,但我宁愿避免这样做。

    真的没有那么大:)

    string = "M\\xC3\\xB6bler"
    string.encoding
    # => #<Encoding:UTF-8>
    
    puts string.gsub(/\\x([0-9a-zA-Z]{2})/) { $1.to_i(16).chr }
    # => Möbler
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-07
      • 2016-11-08
      • 1970-01-01
      • 1970-01-01
      • 2017-03-08
      • 2011-12-01
      • 1970-01-01
      相关资源
      最近更新 更多