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!
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 .
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):
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
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.
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
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"})