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" を入れましたが、エンコードオプションの有無にかかわらず、役に立ちませんでした。

DBは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" (... "title", ...) VALUES (..., 'St?dtische Galerie im Lenbachhaus', ...) RETURNING "id"):

:(

4

3 に答える 3

3

あなたが推測したように、問題はファイルのエンコードの問題である可能性があります。最も可能性の高いシナリオは、ファイルが実際には UTF-8 でエンコードされていないため、アプリケーションの残りの部分が外国のエンコードを認識できないことです。また、エンコーディングで使用されるバイトの 1 つが 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はこの文字列の長さを33ではなく34として返します。ただし、検証を実行するなど、文字列で何かを実行するまで、これは影響しません。

>> "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

使用しているデータベースの種類はわかりませんが、DB が UTF-8 用に構成されておらず、代わりに ASCII を想定している可能性が非常に高くなります。非 ASCII 文字を投げると、データベースと対話に使用している gem または ORM に応じて、文字列が切り捨てられたり、文字が欠落したり、文字がプレースホルダーに置き換えられたりする可能性があります。データベースを構築するときは、データベースが UTF-8 用に構成されていることを確認するか、プッシュするテキストがエンコードされていることを確認して、破損や損失なしで往復できるようにします。私はあなたと同じように、難しい方法でその教訓を学びました。

データベースのログを確認するか、コードを確認して、データベース挿入のログとエラーおよび警告メッセージを有効にできるかどうかを確認してください。

多くのデータベースで警告とエラーを無効にするのは簡単ですが、開発中はそうしたくないでしょう。これらのメッセージは重要であり、大きな問題が発生する前兆となる可能性があります。それらを無視してコードを本番環境にプッシュすることは、眠れない夜の本当のレシピになる可能性があります.

于 2011-02-19T23:56:21.643 に答える