如何将弃用的iconv更改为String#encode以进行无效的UTF8更正

时间:2012-02-03 10:00:37

标签: ruby unicode character-encoding iconv

我从网络获取资源,有时材料的编码不是100%UTF8字节序列有效。我使用iconv静静地忽略这些序列以获得一个清理过的字符串。

@iconv = Iconv.new('UTF-8//IGNORE', 'UTF-8')
valid_string = @iconv.iconv(untrusted_string)

但是现在iconv已被弃用,我看到它的弃用警告很多。

iconv将来会被弃用,请使用String #code

我尝试使用String#encode的{​​{1}}和:invalid选项对其进行转换,但似乎没有工作(即错误的字节序列尚未删除)。使用String#encode的正确方法是什么?

2 个答案:

答案 0 :(得分:7)

在这个问题中已经回答了这个问题:

Is there a way in ruby 1.9 to remove invalid byte sequences from strings?

使用

untrusted_string.chars.select{|i| i.valid_encoding?}.join

untrusted_string.encode('UTF-8', :invalid => :replace, :replace => '').encode('UTF-8')

答案 1 :(得分:6)

Martijn与之相关的问题似乎是两种最佳方式,但Martijn在将第二种方法复制到他的答案时做出了可理解但不正确的改变。执行.encode(' UTF-8',< options>)。encode(' UTF-8')不起作用。正如另一个问题的原始答案所示,关键是编码为不同的编码,然后再编码为UTF-8。如果您的原始字符串已在ruby的内部标记为UTF-8,则ruby将忽略任何将其编码为UTF-8的调用。

在下面的示例中,我将使用"#{0xFF.chr} b" .force_encoding(' UTF-8')来生成ruby认为的字符串是UTF-8但包含无效的UTF-8字节。

1.9.3p194 :019 > "a#{0xFF.chr}b".force_encoding('UTF-8')
 => "a\xFFb" 
1.9.3p194 :020 > "#{0xFF.chr}".force_encoding('UTF-8').encoding
 => #<Encoding:UTF-8> 

请注意UTF-8的编码无效:

1.9.3p194 :016 > "a#{0xFF.chr}b".force_encoding('UTF-8').encode('UTF-8', :invalid => :replace, :replace => '').encode('UTF-8')
 => "a\xFFb" 

但编码到其他东西(UTF-16)然后再回到UTF-8会清除字符串:

1.9.3p194 :017 > "a#{0xFF.chr}b".force_encoding('UTF-8').encode('UTF-16', :invalid => :replace, :replace => '').encode('UTF-8')
 => "ab"