Ruby将CSV文件读取为UTF-8和/或将ASCII-8Bit编码转换为UTF-8

use*_*146 55 ruby csv string encoding utf-8

我正在使用ruby 1.9.2

我正在尝试解析包含一些法语单词的CSV文件(例如spécifié)并将内容放在MySQL数据库中.

当我从CSV文件中读取行时,

file_contents = CSV.read("csvfile.csv", col_sep: "$")
Run Code Online (Sandbox Code Playgroud)

这些元素以ASCII-8BIT编码的字符串形式返回(spécifié变为sp\xE9cifi\xE9),然后像"spécifié"这样的字符串未正确保存到我的MySQL数据库中.

Yehuda Katz说ASCII-8BIT实际上是"二进制"数据,这意味着CSV不知道如何读取适当的编码.

所以,如果我尝试使CSV强制编码如下:

file_contents = CSV.read("csvfile.csv", col_sep: "$", encoding: "UTF-8")

我收到以下错误

ArgumentError: invalid byte sequence in UTF-8: 
Run Code Online (Sandbox Code Playgroud)

如果我回到我原来的ASCII-8BIT编码字符串并检查我的CSV读取为ASCII-8BIT的字符串,它看起来像"非sp\xE9cifi\xE9"而不是"非spécifié".

这样做我无法将"Non sp\xE9cifi\xE9"转换为"非spécifié" "Non sp\xE9cifi\xE9".encode("UTF-8")

因为我收到这个错误:

Encoding::UndefinedConversionError: "\xE9" from ASCII-8BIT to UTF-8,

Katz指出会发生这种情况,因为ASCII-8BIT实际上并不是一个正确的字符串"编码".

问题:

  1. 我可以使用CSV以适当的编码读取我的文件吗?如果是这样,怎么样?
  2. 如何将ASCII-8BIT字符串转换为UTF-8以便在MySQL中正确存储?

mu *_*ort 60

deceze是对的,即ISO8859-1(AKA Latin-1)编码文本.试试这个:

file_contents = CSV.read("csvfile.csv", col_sep: "$", encoding: "ISO8859-1")
Run Code Online (Sandbox Code Playgroud)

如果这不起作用,您可以使用以下内容Iconv来修复单个字符串:

require 'iconv'
utf8_string = Iconv.iconv('utf-8', 'iso8859-1', latin1_string).first
Run Code Online (Sandbox Code Playgroud)

如果latin1_string"Non sp\xE9cifi\xE9",那么utf8_string"Non spécifié".此外,Iconv.iconv可以一次取消整个数组:

utf8_strings = Iconv.iconv('utf-8', 'iso8859-1', *latin1_strings)
Run Code Online (Sandbox Code Playgroud)

使用较新的Rubies,您可以执行以下操作:

utf8_string = latin1_string.force_encoding('iso-8859-1').encode('utf-8')
Run Code Online (Sandbox Code Playgroud)

其中,latin1_string认为它是ASCII-8BIT,但确实是在ISO 8859.

  • 请注意,Ruby现在要求您使用`String #codes`而不是使用`iconv`. (3认同)

knu*_*nut 26

使用ruby> = 1.9即可使用

file_contents = CSV.read("csvfile.csv", col_sep: "$", encoding: "ISO8859-1:utf-8")
Run Code Online (Sandbox Code Playgroud)

ISO8859-1:utf-8意味着:csv文件是ISO8859-1编码的,但将内容转换为utf-8

如果您更喜欢更详细的代码,可以使用:

file_contents = CSV.read("csvfile.csv", col_sep: "$", 
    external_encoding: "ISO8859-1", 
    internal_encoding: "utf-8"
  )
Run Code Online (Sandbox Code Playgroud)