2

我有一个 CSV 文件,其中包含这样的行:

...,"Städtische Galerie im Lenbachhaus",...

我正在使用带有 FasterCSV gem 的 Ruby 1.8,如下所示:

FasterCSV.foreach(file, :encoding => 'u', :headers => :first_row) do |r|
    as = ImportObject.create!(r.to_hash)
end

对于大多数行,它工作正常,但对于这些行,带有特殊字符的字段被截断,因此我们将“St”保存在数据库中。

我已经把 $KCODE="u" 和有/没有编码选项,无济于事。

数据库是 MySQL。

编辑:

我尝试将代码推送到 Heroku (Postgres),现在得到一个新错误:

2011-02-19T17:19:01-08:00 app[web.1]: ActiveRecord::StatementInvalid (PGError: ERROR: invalid byte sequence for encoding "UTF8": 0xe46474

2011-02-19T17:19:01-08:00 app[web.1]:提示:如果字节序列与服务器预期的编码不匹配,也可能发生此错误,该编码由“client_encoding”控制。

2011-02-19T17:19:01-08:00 app[web.1]: : INSERT INTO "import_objects" (... "title", ...) VALUES (..., 'St?dtische Galerie im Lenbachhaus',...)返回“id”):

:(

4

3 回答 3

3

正如您所推测的那样,问题可能是文件编码问题。最可能的情况是您的文件实际上并未使用 UTF-8 编码,因此您的应用程序的其余部分无法识别外部编码。也有可能 - 但我认为不太可能 - 编码中使用的字节之一是 ASCII 中的引号或逗号,这会弄乱 FasterCSV 解析数据。

首先,在 CSV 文件中创建一个仅包含“问题行”的测试文件。接下来,读取文件中的数据:

text_in = File.read('data.csv')

现在你必须转换它。问题是,你真的不知道它是什么。你将不得不尝试一些不同的事情。我最好的猜测是文本是 Latin-1 编码的。

require 'iconv'
text_out = Iconv.conv("UTF8", "LATIN1", text_in)

现在尝试导入此数据。或者,您可以写入磁盘并打开它,看看它是否正确编码。

但老实说,您可以在 Ruby 之外更轻松地做到这一点。

$ iconv -t UTF8 -f LATIN1 < data.csv > data_conv.csv

进一步阅读:

于 2011-02-20T01:49:43.613 回答
1

问题不是 FasterCSV,因为在我的测试中,FasterCSV 读取这些数据没有问题。例如:

>> FasterCSV.parse("a,Städtische Galerie im Lenbachhaus,b,ä", :headers => [:a,:b,:c,:d]) do |r|
|    r = r.to_hash
|    p r
|    puts r[:d]
|  end  
{:c=>"b", :a=>"a", :d=>"\303\244", :b=>"Städtische Galerie im Lenbachhaus"}
ä

请注意,Ruby 1.8 不能正确处理 unicode 字符,但这主要会影响String#length. 例如,Ruby 会将此字符串的长度返回为 34 而不是 33。但是,除非您对字符串执行某些操作,例如对其运行验证,否则这不会产生影响。

>> "Städtische Galerie im Lenbachhaus".length
=> 34
>> "Stadtische Galerie im Lenbachhaus".length
=> 33

所以我的猜测是它与ImportObject您的数据库连接的配置方式或方式有关。


这些测试中使用的 Ruby 版本:

>> RUBY_DESCRIPTION 
=> "ruby 1.8.7 (2010-04-19 patchlevel 253) [i686-darwin10.4.0], MBARI 0x6770, Ruby Enterprise Edition 2010.02"
于 2011-02-19T23:49:16.007 回答
1

你没有说你正在使用什么数据库类型,但很可能数据库没有配置为 UTF-8,而是期待 ASCII。向其抛出非 ASCII 字符可能会导致字符串被截断、字符丢失或被占位符替换的字符,具体取决于数据库以及您使用的与其对话的 gem 或 ORM。当我建立一个数据库时,我确保它是为 UTF-8 配置的,或者,我确保我推入它的文本是经过编码的,这样它就可以在不损坏或丢失的情况下进行往返。我以和你一样的方式学到了这一课,很难。

检查数据库的日志,和/或检查您的代码以查看您是否可以为数据库插入启用日志记录以及错误和警告消息。

禁用大量数据库的警告和错误很容易,但在开发过程中您不想这样做。这些信息很重要,可能预示着即将出现的大问题。忽略它们并将代码推送到生产环境可能是不眠之夜的真正秘诀。

于 2011-02-19T23:56:21.643 回答