我正在使用 ruby 1.9.2
我正在尝试解析包含一些法语单词(例如 spécifié)的 CSV 文件,并将内容放入 MySQL 数据库中。
当我从 CSV 文件中读取行时,
file_contents = CSV.read("csvfile.csv", col_sep: "$")
返回的元素是 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:
如果我回到原来的 ASCII-8BIT 编码字符串并检查我的 CSV 读取为 ASCII-8BIT 的字符串,它看起来像这样“Non sp\xE9cifi\xE9”而不是“Non spécifié”。
我无法通过这样做将“Non sp\xE9cifi\xE9”转换为“Non spécifié”
"非 sp\xE9cifi\xE9".encode("UTF-8")
因为我得到这个错误:
Encoding::UndefinedConversionError: "\xE9"从 ASCII-8BIT 到 UTF-8
,
Katz 表示会发生这种情况,因为 ASCII-8BIT 并不是真正合适的字符串“编码”。
问题:
- 我能否让 CSV 以适当的编码读取我的文件?如果是,怎么做?
- 如何将 ASCII-8BIT 字符串转换为 UTF-8 以便在 MySQL 中正确存储?
最佳答案
deceze是的,那是 ISO8859-1 (AKA Latin-1) 编码的文本。试试这个:
file_contents = CSV.read("csvfile.csv", col_sep: "$", encoding: "ISO8859-1")
如果这不起作用,您可以使用 Iconv
用这样的东西修复单个字符串:
require 'iconv'
utf8_string = Iconv.iconv('utf-8', 'iso8859-1', latin1_string).first
如果 latin1_string
是 "Non sp\xE9cifi\xE9"
,那么 utf8_string
将是 "Non spécifié"
。此外,Iconv.iconv
可以一次分解整个数组:
utf8_strings = Iconv.iconv('utf-8', 'iso8859-1', *latin1_strings)
使用较新的 Rubies,您可以执行以下操作:
utf8_string = latin1_string.force_encoding('iso-8859-1').encode('utf-8')
latin1_string
认为它是 ASCII-8BIT 但实际上是 ISO-8859-1。
关于Ruby 将 CSV 文件读取为 UTF-8 和/或将 ASCII-8Bit 编码转换为 UTF-8,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7047944/