当前位置:  开发笔记 > 后端 > 正文

ruby 1.9:UTF-8中的无效字节序列

如何解决《ruby1.9:UTF-8中的无效字节序列》经验,为你挑选了4个好方法。

我在Ruby(1.9)中编写了一个爬虫程序,它从很多随机站点中消耗了大量的HTML.
当试图提取链接时,我决定使用.scan(/href="(.*?)"/i)而不是nokogiri/hpricot(主要加速).问题是我现在收到很多" invalid byte sequence in UTF-8"错误.
根据我的理解,该net/http库没有任何特定于编码的选项,并且所引入的内容基本上没有正确标记.
实际使用传入数据的最佳方法是什么?我尝试.encode使用替换和无效选项集,但到目前为止没有成功...



1> ecerulm..:

在Ruby 1.9.3中,可以使用String.encode来"忽略"无效的UTF-8序列.这是一个可以在1.8(iconv)和1.9(String #coding)中工作的片段:

require 'iconv' unless String.method_defined?(:encode)
if String.method_defined?(:encode)
  file_contents.encode!('UTF-8', 'UTF-8', :invalid => :replace)
else
  ic = Iconv.new('UTF-8', 'UTF-8//IGNORE')
  file_contents = ic.iconv(file_contents)
end

或者如果你有非常麻烦的输入,你可以进行从UTF-8到UTF-16并返回到UTF-8的双重转换:

require 'iconv' unless String.method_defined?(:encode)
if String.method_defined?(:encode)
  file_contents.encode!('UTF-16', 'UTF-8', :invalid => :replace, :replace => '')
  file_contents.encode!('UTF-8', 'UTF-16')
else
  ic = Iconv.new('UTF-8', 'UTF-8//IGNORE')
  file_contents = ic.iconv(file_contents)
end


还有`force_encoding`选项.如果您读取ISO8859-1作为UTF-8(因此该字符串包含无效的UTF-8),那么您可以使用the_string.force_encoding("ISO8859-1")将其"重新解释"为ISO8859-1并且正常工作使用该字符串进行实际编码.
我认为双重转换是有效的,因为它强制进行编码转换(并检查无效字符).如果源字符串已经以UTF-8编码,那么只调用`.encode('UTF-8')`是无操作,并且不运行任何检查.[用于编码的Ruby核心文档](http://www.ruby-doc.org/core-1.9.3/String.html#method-i-encode).但是,将其转换为UTF-16会首先强制执行对无效字节序列的所有检查,并根据需要进行替换.
对于一些有问题的输入,我还使用从UTF-8到UTF-16的双重转换,然后返回到UTF-8`file_contents.encode!('UTF-16','UTF-8',:invalid =>:replace, :replace =>'')``file_contents.encode!('UTF-8','UTF-16')`
这个双重编码技巧刚刚保存了我的培根!我想知道为什么它是必需的?

2> Amir Raminfa..:

接受的答案和其他答案对我有用.我发现这个职位这表明

string.encode!('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')

这解决了我的问题.



3> Marc Seeger..:

我目前的解决方案是运行:

my_string.unpack("C*").pack("U*")

这将至少摆脱我的主要问题的例外


我正在使用这个方法与`valid_encoding?`结合使用,它似乎可以检测到什么时候出错了.`val.unpack('C*').pack('U*')if!val.valid_encoding?`.

4> Ranjithkumar..:

试试这个:

def to_utf8(str)
  str = str.force_encoding('UTF-8')
  return str if str.valid_encoding?
  str.encode("UTF-8", 'binary', invalid: :replace, undef: :replace, replace: '')
end

推荐阅读
吻过彩虹的脸_378
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有