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

lul*_*ala 4 ruby unicode character-encoding iconv

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

@iconv = Iconv.new('UTF-8//IGNORE', 'UTF-8')
valid_string = @iconv.iconv(untrusted_string)
Run Code Online (Sandbox Code Playgroud)

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

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

我尝试使用String#encode's :invalid:replace选项转换它,但它似乎没有工作(即没有删除不正确的字节序列).使用String#encode的正确方法是什么?

Mar*_*ijn 7

这个问题在这个问题中得到了回答:

在ruby 1.9中是否有一种方法可以从字符串中删除无效的字节序列?

使用其中之一

untrusted_string.chars.select{|i| i.valid_encoding?}.join
Run Code Online (Sandbox Code Playgroud)

要么

untrusted_string.encode('UTF-8', :invalid => :replace, :replace => '').encode('UTF-8')
Run Code Online (Sandbox Code Playgroud)


Jas*_*iss 6

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

在下面的例子中,我将使用"a#{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> 
Run Code Online (Sandbox Code Playgroud)

请注意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" 
Run Code Online (Sandbox Code Playgroud)

但编码到其他东西(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" 
Run Code Online (Sandbox Code Playgroud)