web-dev-qa-db-ja.com

CSV-引用符で囲まれていないフィールドでは、\ rまたは\ n(2行目)は許可されません

CSVファイルを解析しようとするとエラーメッセージが表示される引用符で囲まれていないフィールドでは、\ rまたは\ n(2行目)は許可されません。

私はここSO類似のトピックで見つけました、ここで以下を行うためのヒントがありました:

  CSV.open('file.csv', :row_sep => "\r\n") do |csv|

しかし、残念ながら彼はうまくいきません... CSVファイルを変更できないので、コードで修正する必要があります。

[〜#〜] edit [〜#〜] CSVファイルのサンプル:

A;B;C
1234;...

それを行う方法はありますか?

どうもありがとう!

19
user984621

まず、列区切り文字を ';'に設定する必要があります。これは、CSVファイルが解析される通常の方法ではないためです。これは私のために働きました:

CSV.open('file.csv', :row_sep => :auto, :col_sep => ";") do |csv|
    csv.each { |a,b,c| puts "#{a},#{b},#{c}" } 
end

1.9.2 CSVドキュメントから:

自動検出は、データを先読みして、次の\r\n\n、または\rシーケンスを探します。シーケンスは、引用符で囲まれたフィールドで発生しても選択されます。ただし、そこでは同じ行末があると仮定します。

15
jslivka

奇妙なフォーマットを使用している可能性のあるプログラム(Excelやスプレッドシートなど)によってCSVが変更または保存された場合のより簡単な解決策:

  1. 任意のplainテキストエディターでファイルを開きます(Sublime Text 3を使用しました)。
  2. Enterキーを押して、どこかに新しい行を追加します
  3. ファイルを保存します
  4. 追加した行を削除します
  5. ファイルを再度保存します
  6. インポートを再試行してください。エラーはなくなりました
13
Mike S

私にとってはLinkedIn CSVをインポートしていてエラーが発生しました。

次のように空白行を削除しました:

  def import
    csv_text = File.read('filepath', :encoding => 'ISO-8859-1')
    #remove blank lines from LinkedIn
    csv_text = csv_text.gsub /^$\n/, ''
    @csv = CSV.parse(csv_text, :headers => true, skip_blanks: true)
  end
3

私はこれが古い投稿であることを理解していますが、最近、標準のRuby CSVライブラリで解析できない、不適切にフォーマットされたCSVファイルで同様の問題が発生しました。

すぐにファイルを解析する SmarterCSV gemを試しました。これは外部ライブラリなので、誰にとっても最善の解決策とは言えないかもしれませんが、自分でファイルを解析するよりも優れています。

opts = { col_sep: ';', file_encoding: 'iso-8859-1', skip_lines: 5 }
SmarterCSV.process(file, opts).each do |row|
  p row[:someheader]
end
1
Cimm

私の場合、エンコーディングと、データ内で発生しないことが保証されている引用文字を提供する必要がありました

CSV.read("file.txt", 'rb:bom|UTF-16LE', {:row_sep => "\r\n", :col_sep => "\t", :quote_char => "\x00"})
1
Danil Gaponov

セルに改行が含まれるExcelからのファイルを処理する必要がある場合は、解決策もあります。

この方法の大きな欠点は、文字列にセミコロンや二重引用符を使用できないことです。

私はセミコロンなしで行くことを選択します

if file.respond_to?(:read)
  csv_contents = file.read
elsif file_data.respond_to?(:path)
  csv_contents = File.read(file.path)
else
  logger.error "Bad file_data: #{file_data.class.name}: #{file_data.inspect}"
  return false
end

result = "string"
csv_contents = csv_contents.force_encoding("iso-8859-1").encode('utf-8') # In my case the files are latin 1...

# Here is the important part (Remove all newlines between quotes):
while !result.nil?
  result = csv_contents.sub!(/(\"[^\;]*)[\n\r]([^\;]*\")/){$1 + ", " + $2}
end

CSV.parse(csv_contents, headers: false, :row_sep => :auto, col_sep: ";") do |row|
  # do whatever
end

私にとって、このソリューションは問題なく機能します。大きなファイルを扱う場合、問題が発生する可能性があります。

引用符なしで移動したい場合は、正規表現のセミコロンを引用符に置き換えてください。

0
Markus Andreas