Ruby 如何将不推荐使用的iconv更改为字符串#编码以进行无效的UTF8更正

Ruby 如何将不推荐使用的iconv更改为字符串#编码以进行无效的UTF8更正,ruby,unicode,character-encoding,iconv,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#encode的:invalid和:replace选项转换它,但

我从网络上获取资料,有时材料的编码不是100%UTF8字节序列有效。我使用iconv以静默方式忽略这些序列以获得一个干净的字符串

@iconv = Iconv.new('UTF-8//IGNORE', 'UTF-8')
valid_string = @iconv.iconv(untrusted_string)
但是现在iconv已经被弃用了,我看到它的弃用警告很多

iconv将在将来被弃用,请使用字符串编码


我尝试使用
String#encode
:invalid
:replace
选项转换它,但它似乎不起作用(即未删除不正确的字节序列)。使用字符串#编码的正确方法是什么?

这个问题已经得到了回答:

使用其中一个

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


Martijn所联系的问题似乎有两种最好的解决方法,但是Martijn在这里复制第二种方法的答案时做了一个可以理解但不正确的改变。正在执行.encode('UTF-8',)。encode('UTF-8')不起作用。如另一个问题的原始答案所示,关键是编码为不同的编码,然后返回UTF-8。如果您的原始字符串已经在ruby的内部标记为UTF-8,那么ruby将忽略任何将其编码为UTF-8的调用

在下面的示例中,我将使用“a#{0xFF.chr}b”。强制_编码('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-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" 

我认为你的尝试是非常危险的。文本编码就像怀孕:要么你有UTF8要么你没有。你不能只拥有一点UTF8。如果出现错误,您必须中止。否则,您的转换器可能容易受到恶意准备字符串的攻击。我正在编写一个爬虫程序,将有一个页面有点无效。所以清理字节是我唯一能做的。实际上你是对的。如果我一直使用UTF-8,在字符串上使用gsub仍然会引发“无效编码”错误。但你的回答解决了这个问题。我之前一定做了一个糟糕的测试。答案是更改编码或编码没有任何作用。因此,在编写
wtf.encode('UTF-8',诸如此类).encode('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" 
1.9.3p194 :017 > "a#{0xFF.chr}b".force_encoding('UTF-8').encode('UTF-16', :invalid => :replace, :replace => '').encode('UTF-8')
 => "ab"