fot*_*nus 17 ruby encoding ruby-on-rails
自Rails版本1以来,我有一个Rails应用程序从迁移中幸存下来,我想忽略它上面的所有无效字节序列,以保持向后兼容性.
我不知道输入编码.
例:
> "- 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>'
Run Code Online (Sandbox Code Playgroud)
我可以通过使用以下内容在一行中克服此问题,例如:
> "- Men\xFC -".unpack("C*").pack("U*").split("n")
=> ["- Me", "ü -"]
Run Code Online (Sandbox Code Playgroud)
但是,我想始终忽略无效的字节序列并禁用此错误.在Ruby本身或Rails中.
Dav*_*son 16
我不认为你可以在没有太大困难的情况下全局关闭UTF-8检查.我将专注于修复进入应用程序的所有字符串,在它们进入的边界(例如,当您查询数据库或接收HTTP请求时).
让我们假设进来的字符串有BINARY(也就是ASCII-8BIT编码).这可以这样模拟:
s = "Men\xFC".force_encoding('BINARY') # => "Men\xFC"
Run Code Online (Sandbox Code Playgroud)
然后我们可以使用String#encode将它们转换为UTF-8,并用UTF-8替换字符替换任何未定义的字符:
s = s.encode("UTF-8", invalid: :replace, undef: :replace) # => "Men\uFFFD"
s.valid_encoding? # => true
Run Code Online (Sandbox Code Playgroud)
不幸的是,上面的步骤最终会破坏很多UTF-8代码点,因为它们中的字节不会被识别.如果您有一个三字节的UTF-8字符,如"\ uFFFD",它将被解释为三个单独的字节,每个字节将被转换为替换字符.也许你可以这样做:
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
Run Code Online (Sandbox Code Playgroud)
这是我能想到的最好的.不幸的是,我不知道告诉Ruby将字符串视为UTF-8并只替换所有无效字节的好方法.