当我们导入csv数据时,如何消除"UTF-8中的无效字节序列"

jpw*_*ynn 61 ruby utf-8

我们允许用户通过csv导入数据(使用ruby 1.9.2,因此它的速度更快).

当然,它是用户数据,可能无法正确消毒.

当我们尝试在/ index方法中显示数据时,我们有时会得到错误"UTF-8中的无效字节序列"指向我们的erb,其中我们显示了一个字段widget.name

当我们进行导入时,我们希望强制传入的数据有效...是否有一个ruby运算符,它将字符串映射到有效的utf8字符串,例如类似

goodstring = badstring.no_more_invalid_bytes
Run Code Online (Sandbox Code Playgroud)

"坏"数据的一个例子是char,它看起来像连字符,但不是常规的ascii连字符.我们更喜欢将非utf-8字符映射到合理的ascii等效字符(umlat-u to u to exmaple)但是我们可以简单地将字符剥离到.

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


注意:这是一个数据示例.该文件来自窗口,是8位ascii.当我们导入它并在我们的erb中我们显示widget.name.inspect(而不是widget.name)时,我们得到:"Chains\x96附件"

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

---当我们改变我们的csv解析以分配fldval = d.encode('UTF-8')时,它会抛出此错误:

Encoding::UndefinedConversionError in StoresController#importfinderitems
"\x96" from ASCII-8BIT to UTF-8
Run Code Online (Sandbox Code Playgroud)

即使我们简单地剥离非ascii,我们正在寻找的是一种简单的方法来强制它无论原始类型是否有效utf8.


虽然不像强制编码那样"好",但这对我们的导入时间有点小费用:d.to_s.strip.gsub(/\P {ASCII} /,'')谢谢你,Mladen!

Tru*_* Lê 123

Ruby 1.9 CSV具有与m17n一起使用的新解析器.解析器使用字符串中的IO对象编码.以下方法:::foreach, ::open, ::read, and ::readlines可以选择:encoding您可以指定编码的可选选项.

例如:

CSV.read('/path/to/file', :encoding => 'windows-1251:utf-8')
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 'windows-1251:utf-8'是什么意思? (3认同)
  • 有没有办法强制任何编码,而不仅仅是Windows-1251,UTF-8?像'????:utf-8'之类的东西?即我只是想确保我导入的CSV始终是UTF8,并不真正关心它最初的编码. (3认同)

cor*_*ard 13

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

请注意,您需要知道源代码编码才能可靠地转换它.像我在其他答案中链接到的那些库可以帮助您确定这一点.

此外,如果您不从文件加载数据,则可以非常轻松地转换1.9.2中字符串的编码:

'string'.encode('UTF-8')
Run Code Online (Sandbox Code Playgroud)

但是,您很少使用其他编码构建字符串,如果可能的话,最好在将其读入您的环境时进行转换.

  • Ruby 1.9内置了CSV类,它的`read`方法接收可选的`:encoding`参数,所以你可以在加载时使用`CSV.read('/ path/to/file')自动转码你的文件, :encoding =>'windows-1251:utf-8')`. (87认同)

小智 12

CSV.parse(File.read('/path/to/csv').scrub)
Run Code Online (Sandbox Code Playgroud)


joe*_*son 7

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

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

对于异常字符串,例如从未知编码文件加载的字符串,使用#encode而不是正则表达式,#gsub或#delete是明智的,因为这些都需要解析字符串 - 但如果字符串被破坏,它无法解析,因此这些方法失败了.

如果你收到这样的消息:

error ** from ASCII-8BIT to UTF-8
Run Code Online (Sandbox Code Playgroud)

然后你可能试图转换已经是UTF-8的二进制字符串,你可以强制使用UTF-8:

str.force_encoding('UTF-8')
Run Code Online (Sandbox Code Playgroud)

如果你知道原始字符串不是二进制UTF-8,或者输出字符串有非法字符,那么请阅读Ruby编码音译.


dom*_*dom 6

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

'Your string with strange stuff #@~'.mb_chars.tidy_bytes
Run Code Online (Sandbox Code Playgroud)

它会删除无效的 utf-8 字符并将其替换为有效的字符。更多信息:https : //apidock.com/rails/String/mb_chars