2012-02-03 50 views
4

我从网络获取源代码,有时材料的编码不是100%UTF8字节序列有效。我使用iconv默默地忽略这些序列来获得一个清理过的字符串。如何将不推荐使用的iconv更改为字符串#对无效的UTF8更正进行编码

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

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

的iconv将在未来被废弃,用String#编码

我试图转换它,使用String#encode:invalid:replace选项,但似乎并不奏效(即不正确的字节序列尚未被删除)。什么是使用String#编码的正确方法?

+0

我认为你正在尝试的是非常危险的。文本编码就像怀孕一样:要么有UTF8,要么没有。你不能只有一点UTF8。如果有错误,你*有*放弃。否则,您的转换器可能容易受到恶意准备字符串的攻击。 – 2012-02-03 10:06:17

+0

我正在写一个履带式,那里有一个网页,有点无效。因此清理字节是我所能做的。 – lulalala 2012-02-03 10:40:25

回答

6

问题两个最好的方法来做到这一点,但Martijn做了一个可以理解的b当在这里复制第二种方法到他的答案时,不正确的改变。做.encode('UTF-8',<选项>).encode('UTF-8')不起作用。正如在另一个问题的原始答案中所指出的那样,关键在于编码为不同的编码,然后返回到UTF-8。如果您的原始字符串已经在ruby的内部标记为UTF-8,那么ruby将忽略任何调用将其编码为UTF-8。

在以下示例中,我将使用“a#{0xFF.chr} b”.force_encoding('UTF-8')生成一个字符串,该字符串认为是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" 
+0

其实你是对的。如果我始终使用UTF-8,则在字符串上使用gsub仍会引发“无效编码”错误。但是你的答案解决了这个问题。我早一定做了一个糟糕的测试。 – lulalala 2012-09-26 01:35:26

7

这已经回答了这个问题:

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

使用的Martijn链接到了表里如一是要么

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

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

答案表示更改编码或编码不会执行任何操作。所以在编写wtf.encode('UTF-8',blah blah).encode('UTF-8')'时,首先编码在这里没有效果。 – nurettin 2013-01-03 07:32:32

相关问题