使用Ruby 1.8 / FasterCSV尝试使用umlaut等解析CSV文件的问题

时间:2011-02-19 23:08:51

标签: ruby string encoding csv fastercsv

我有一个包含这样的行的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:错误:无效字节   用于编码“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”(...   “标题”,......)价值观(......,'St?dtische   Galerie im Lenbachhaus',...)   返回“id”):

:(

3 个答案:

答案 0 :(得分: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

进一步阅读:

答案 1 :(得分: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"

答案 2 :(得分:1)

您没有说出您正在使用的数据库类型,但很可能没有为UTF-8配置数据库,而是期望使用ASCII。在它上面输入非ASCII字符可能会导致截断字符串,缺少字符或用占位符替换的字符,具体取决于数据库以及您用来与之交谈的gem或ORM。当我构建一个数据库时,我确保它配置为UTF-8,或者,我确保我推入的文本被编码,这样它就可以进行往返而不会损坏或丢失。我以同样的方式学到了这一课,艰难的方式。

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

很容易通过大量数据库禁用警告和错误,但在开发期间您不希望这样做。这些信息非常重要,可以发出重大问题。忽略它们并将代码推向生产可能是不眠之夜的真正秘诀。