在我的 JRuby 应用程序中,我从两个来源获取输入:
一些外部数据(应该)被编码为 ISO_8859_1,而我在内部将其处理为 UTF_8 并生成 UTF_8 作为输出。
不幸的是,有时会出现编码错误:数据偶尔包含无效 ISO_8859_1 的字节,并且此问题不会得到修复。该规范要求简单地丢弃那些非法输入字节。
对于文件,我正在使用
读取文件string = File.new(filename, {external_encoding: Encoding::ISO_8859_1, internal_encoding: Encoding::UTF_8, converters: UTF8_CONVERTER})
converts子句会注意跳过非法输入字节。
对于从 Java 端接收到的字符串,我当然可以通过执行以下操作将它们转换为 UTF_8:
string = iso_string.encode(Encoding::UTF_8)
但是我怎样才能在这里捕获非法字符呢?根据我对 Ruby 文档对
encode
方法的理解,可以在目标编码之后声明的选项不提供 converts 键。
更新
这是一个简单的例子来演示这个问题:
(1) 好的案例(没有错误)
s = [49, 67].pack('C*')
put s
puts s.encoding
u = s.encode(Encoding::UTF_8)
puts u
puts u.encoding
此打印
1C
ASCII-8BIT
1C
UTF-8
(2)错误案例
x = [49, 138, 67].pack('C*')
x.encode(Encoding::UTF_8)
如预期,引发 UndefinedConversionError: ""\x8A"" 从 ASCII-8BIT 到 UTF-8
我尝试过的(虽然没有记录):
t = x.encode(external_encoding: Encoding::ISO_8859_1, internal_encoding: Encoding::UTF_8, converters: UTF8_CONVERTER)
有趣的是,这消除了异常,但转换并未成功。如果我做一个
t.encoding
我仍然看到ASCII-8BIT。似乎什么都没有改变。我希望看到非法字符被删除,即在这种情况下
t
是空字符串。
我发现以下方法可行(针对我问题中的示例):
t = x.encode(Encoding::UTF_8, undef: :replace, replace: '')