web-dev-qa-db-fra.com

CSV - Les champs non marqués ne permettent pas\r ou\n (ligne 2)

Essayer d'analyser un fichier CSV, tout en obtenant le message d'erreur Les champs non marqués n'autorisent pas\r ou\n (ligne 2). .

J'ai trouvé ici à SO un sujet similaire, où un conseil à faire:

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

mais malheureusement, ça ne marche pas avec moi ... Je ne peux pas changer le fichier CSV, alors il faudrait que je le répare dans le code.

EDITéchantillon de fichier CSV:

A;B;C
1234;...

Y a-t-il un moyen de le faire?

Merci beaucoup! 

16
user984621

Tout d’abord, vous devez définir les délimiteurs de colonnes sur ';', car ce n’est pas la méthode normale d’analyse des fichiers CSV. Cela a fonctionné pour moi:

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

À partir de la documentation 1.9.2 CSV: 

La découverte automatique lit en avant dans les données à la recherche de la prochaine séquence \r\n, \n ou \r. Une séquence sera sélectionnée même si elle apparaît Dans un champ entre guillemets, en supposant que vous y ayez les mêmes fins de ligne .

15
jslivka

Solution plus simple si le programme CSV a été touché ou enregistré par un programme ayant pu utiliser un formatage étrange (comme Excel ou Spreadsheet):

  1. Ouvrez le fichier avec n’importe quel éditeur de texte plain (j’ai utilisé Sublime Text 3)
  2. Appuyez sur la touche Entrée pour ajouter une nouvelle ligne n'importe où
  3. Sauvegarder le fichier
  4. Supprimer la ligne que vous venez d'ajouter
  5. Sauvegarder le fichier à nouveau
  6. Recommencez l'importation, l'erreur devrait disparaître
12
Mike S

Pour moi, j'importais LinkedIn au format CSV et j'ai eu l'erreur.

J'ai enlevé les lignes vides comme ceci:

  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
David Silva Smith

Si vous devez traiter des fichiers provenant d'Excel avec des nouvelles lignes dans des cellules, il existe également une solution.

Le gros désavantage de cette méthode est qu’aucun point-virgule ni aucune guillemet double dans les chaînes de caractères ne sont autorisés.

Je choisis d'y aller sans point-virgule

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

Pour moi, la solution fonctionne bien, si vous traitez des fichiers volumineux, vous risquez de rencontrer des problèmes.

Si vous voulez y aller sans guillemets, remplacez simplement les points-virgules dans la regex par des guillemets.

0
Markus Andreas

Je me rends compte qu'il s'agit d'un ancien message, mais j'ai récemment rencontré un problème similaire avec un fichier CSV mal formaté qui n'a pas pu être analysé avec la bibliothèque Ruby CSV standard.

J'ai essayé le SmarterCSV gem qui a analysé le fichier en un rien de temps. C'est une bibliothèque externe, donc ce n'est peut-être pas la meilleure solution pour tout le monde, mais elle vaut mieux que d'analyser le fichier moi-même.

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

Dans mon cas, je devais fournir un encodage et un caractère de citation qui ne risquait pas de se produire dans les données.

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