关于ruby:当我们导入csv数据时,如何消除“UTF-8中的无效字节序列”

when we import csv data, how eliminate “invalid byte sequence in UTF-8”

我们允许用户通过csv导入数据(使用Ruby1.9.2,因此它是fastercsv)。

当然,作为用户数据,它可能没有被正确地清理。

当我们试图以/index方法显示数据时,有时会得到一个错误"invalid byte sequence in utf-8"(以UTF-8表示的字节序列无效),指向我们的erb,在这里我们显示一个字段widget.name。

当我们进行导入时,我们希望强制输入的数据有效…是否有Ruby运算符将字符串映射到有效的utf8字符串,例如

1
goodstring = badstring.no_more_invalid_bytes

"坏"数据的一个例子是char,它看起来像连字符,但不是常规的ASCII连字符。我们更愿意将非UTF-8字符映射为一个合理的ASCII等价字符(umlat-u将u用于exmaple),但我们可以简单地将字符剥离为。

因为这是在导入大量数据时,它需要一个快速的内置操作符,希望…

注意:这里是一个数据示例。该文件来自Windows,是8bit ASCII。当我们导入它时,在erb中显示widget.name.inspect(而不是widget.name),我们得到:"链条x96附件"

所以数据的一个例子是"连字符",实际上是8位代码96。

---当我们将csv解析改为分配fldval=d.encode时("utf-8")。它引发此错误:

1
2
Encoding::UndefinedConversionError in StoresController#importfinderitems
"\x96" from ASCII-8BIT to UTF-8

我们要寻找的是一种简单的方法,可以强制它成为有效的utf8,而不管源类型是什么,即使我们只是简单地去掉非ascii。

虽然没有强制编码那么"好",但这对我们的导入时间来说是一个很小的开销:d.to_s.strip.gsub(/p ascii/,'')谢谢你,米亚丁!


Ruby1.9csv有了新的解析器,可以与m17n一起使用。解析器可以对字符串中的IO对象进行编码。以下方法:::foreach, ::open, ::read, and ::readlines可以选择:encoding选项,您可以指定编码。

例如:

1
CSV.read('/path/to/file', :encoding => 'windows-1251:utf-8')

将所有字符串转换为UTF-8。

也可以使用更标准的编码名称"ISO-8859-1"

1
CSV.read('/..', {:headers => true, :col_sep => ';', :encoding => 'ISO-8859-1'})


我回答了一个类似的问题,该问题涉及使用非UTF-8编码读取1.9.2中的外部文件。我认为这个答案对您有很大帮助:Railsv3/Ruby1.9.2中的字符编码问题

请注意,您需要知道源代码才能可靠地转换它。在我的另一个答案中,有一些库与我链接的库类似,可以帮助您确定这一点。

此外,如果不从文件加载数据,则可以很容易地转换1.9.2中字符串的编码:

1
'string'.encode('UTF-8')

然而,很少有人用另一种编码构建字符串,如果可能的话,最好在将其读取到环境中时将其转换为字符串。


1
CSV.parse(File.read('/path/to/csv').scrub)


Ruby1.9可以通过无效的检测和替换来更改字符串编码:

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

对于不寻常的字符串,例如从未知编码的文件加载的字符串,使用encode而不是regex、gsub或delete是明智的,因为这些都需要解析字符串——但是如果字符串断开,就无法解析,因此这些方法会失败。

如果您收到这样的消息:

1
error ** from ASCII-8BIT to UTF-8

然后,您可能正在尝试转换一个已经是UTF-8格式的二进制字符串,您可以强制使用UTF-8:

1
str.force_encoding('UTF-8')

如果您知道原始字符串不是二进制的UTF-8,或者输出字符串有无数个字符,那么请阅读Ruby编码音译。


如果您使用的是Rails,可以尝试使用以下方法修复它

1
'Your string with strange stuff #@~'.mb_chars.tidy_bytes

它将删除无效的UTF-8字符,并将其替换为有效字符。更多信息:https://apidock.com/rails/string/mbchars


将csv文件上传至google docs电子表格,并重新下载为csv文件。进口,瞧!(在我的案例中工作过)

大概谷歌会把它转换成想要的格式。

来源:Excel到CSV,采用UTF-8编码


正如其他人所提到的,Scrub在Ruby2.1+中很好地清理了这个问题。如果您有一个大文件,您可能不想将整个文件读取到内存中,因此您可以使用如下擦除:

1
2
3
4
data = IO::read(file_path).scrub("")
CSV.parse(data, :col_sep => ',', :headers => true)  do |row|
   puts row
end


只做这个

1
anyobject.to_csv(:encoding => 'utf-8')