ruby-on-rails - 如何全局忽略 UTF-8 字符串中的无效字节序列?

标签 ruby-on-rails ruby encoding

我有一个 Rails 应用程序从 Rails 版本 1 开始迁移,我想忽略它上面的所有 无效字节序列,以保持向后兼容性。

我不知道输入编码

例子:

> "- Men\xFC -".split("n")
ArgumentError: invalid byte sequence in UTF-8
    from (irb):4:in `split'
    from (irb):4
    from /home/fotanus/.rvm/rubies/ruby-2.0.0-rc2/bin/irb:16:in `<main>'

我可以在一行中解决这个问题,例如:

> "- Men\xFC -".unpack("C*").pack("U*").split("n")
 => ["- Me", "ü -"] 

但是我想始终忽略无效的字节序列并禁用此错误。在 Ruby 本身或 Rails 中。

最佳答案

我认为您无法轻松地在全局范围内关闭 UTF-8 检查。相反,我会专注于修复所有进入您的应用程序的字符串,在它们进入的边界处(例如,当您查询数据库或接收 HTTP 请求时)。

让我们假设传入的字符串具有 BINARY(又名 ASCII-8BIT 编码)。这可以像这样模拟:

s = "Men\xFC".force_encoding('BINARY')  # => "Men\xFC"

然后我们可以使用 String#encode 将它们转换为 UTF-8并用 UTF-8 替换字符替换任何未定义的字符:

s = s.encode("UTF-8", invalid: :replace, undef: :replace)  # => "Men\uFFFD"
s.valid_encoding?  # => true

不幸的是,上述步骤最终会破坏大量 UTF-8 代码点,因为其中的字节将无法识别。如果你有一个像“\uFFFD”这样的三字节 UTF-8 字符,它将被解释为三个单独的字节,并且每个字节都会被转换为替换字符。也许你可以这样做:

def to_utf8(str)
  str = str.force_encoding("UTF-8")
  return str if str.valid_encoding?
  str = str.force_encoding("BINARY")
  str.encode("UTF-8", invalid: :replace, undef: :replace)
end

这是我能想到的最好的。不幸的是,我不知道有什么好方法可以告诉 Ruby 将字符串视为 UTF-8 并只替换所有无效字节。

关于ruby-on-rails - 如何全局忽略 UTF-8 字符串中的无效字节序列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16987575/

相关文章:

css - 使用 gulp.task 将 .scss 更改为 .css 时,如何为行注释打开 gulp-compass 配置选项?

ruby-on-rails - 如何命名类名包含数字的 Rails ruby​​ 文件?

ruby-on-rails - Rails 5 API;更新单个记录

ruby-on-rails - Rails secrets.yml VS Dotenv VS Figaro with Capistrano on AWS

ruby-on-rails - 向 ActiveRecord 添加范围会导致层次结构错误

ruby - 在 ruby​​ 的多行 %w 中向行添加注释

java - 如何使 InputStreamReader 在编码无效数据时失败?

c++ - 来自 Symbian 中的 Xml-parser 的 TDesC8 变量中的 UTF8 编码文本锥

windows - 如何在 parse() 之后保留多字节字符

ruby-on-rails - action cable 在本地订阅,但不在 heroku 上订阅