Je recherche des suggestions sur la façon de gérer un fichier csv qui est créé, puis téléchargé par nos clients, et qui peut avoir une virgule dans une valeur, comme un nom d'entreprise.
Certaines des idées que nous examinons sont les suivantes: identificateurs cités (valeur "," valeurs "," etc.) ou en utilisant un | au lieu d'une virgule. Le plus gros problème est que nous devons faciliter les choses, sinon le client ne le fera pas.
Réponses:
Comme d'autres l'ont dit, vous devez échapper les valeurs qui incluent des guillemets. Voici un petit lecteur CSV en C♯ qui prend en charge les valeurs entre guillemets, y compris les guillemets intégrés et les retours chariot.
Soit dit en passant, il s'agit d'un code testé à l'unité. Je le poste maintenant parce que cette question semble se poser beaucoup et que d'autres ne voudront peut-être pas une bibliothèque entière lorsque le simple support CSV fera l'affaire.
Vous pouvez l'utiliser comme suit:
Voici les cours. Notez que vous pouvez également utiliser la
Csv.Escape
fonction pour écrire un CSV valide.la source
Pour 2017, csv est entièrement spécifié - RFC 4180.
C'est une spécification très courante, et est complètement couverte par de nombreuses bibliothèques ( exemple ).
Utilisez simplement n'importe quelle bibliothèque csv facilement accessible , c'est-à-dire RFC 4180.
Il y a en fait une spécification pour le format CSV et comment gérer les virgules:
http://tools.ietf.org/html/rfc4180
Donc, pour avoir des valeurs
foo
etbar,baz
, vous faites ceci:Une autre exigence importante à considérer (également de la spécification):
la source
System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator
.Le format CSV utilise des virgules pour séparer les valeurs, les valeurs qui contiennent des retours chariot, des sauts de ligne, des virgules ou des guillemets doubles sont entourées de guillemets doubles. Les valeurs qui contiennent des guillemets doubles sont citées et chaque citation littérale est échappée par une citation immédiatement précédente: Par exemple, les 3 valeurs:
serait codé comme suit:
Tout champ peut être cité, mais seuls les champs contenant des virgules, CR / NL ou des guillemets doivent être indiqués.
Il n'y a pas de véritable standard pour le format CSV, mais presque toutes les applications suivent les conventions documentées ici . Le RFC qui a été mentionné ailleurs n'est pas une norme pour CSV, c'est un RFC pour l'utilisation de CSV dans MIME et contient des limitations non conventionnelles et inutiles qui le rendent inutile en dehors de MIME.
Un problème que de nombreux modules CSV que j'ai vus ne prennent pas en compte est le fait que plusieurs lignes peuvent être codées dans un seul champ, ce qui signifie que vous ne pouvez pas supposer que chaque ligne est un enregistrement distinct, vous devez soit ne pas autoriser les retours à la ligne dans votre données ou être prêt à gérer cela.
la source
Mettez des guillemets doubles autour des chaînes. C'est généralement ce que fait Excel .
Ala Eli,
la source
Vous pouvez mettre des guillemets doubles autour des champs. Je n'aime pas cette approche, car elle ajoute un autre caractère spécial (la citation double). Définissez simplement un caractère d'échappement (généralement une barre oblique inverse) et utilisez-le partout où vous devez échapper quelque chose:
Vous n'avez pas besoin d'essayer de faire correspondre les guillemets et vous avez moins d'exceptions à analyser. Cela simplifie également votre code.
la source
Il existe une bibliothèque disponible via nuget pour gérer à peu près n'importe quel CSV bien formé (.net) - CsvHelper
Exemple pour mapper à une classe:
Exemple de lecture de champs individuels:
Laisser le client gérer le format de fichier:
,
est le délimiteur de champ standard,"
est la valeur standard utilisée pour échapper les champs qui contiennent un délimiteur, un guillemet ou une fin de ligne.Pour utiliser (par exemple)
#
des champs et'
des échappements:Plus de documentation
la source
CsvHelper
bibliothèque pour résoudre le problème de l'OP.Comme mentionné dans mon commentaire à la réponse de harpo, sa solution est bonne et fonctionne dans la plupart des cas, mais dans certains cas, lorsque les virgules sont directement adjacentes, elles ne se divisent pas sur les virgules.
Cela est dû au fait que la chaîne Regex se comporte de manière inattendue en tant que chaîne vertabim. Pour que ce comportement soit correct, tous les "caractères de la chaîne d'expression régulière doivent être échappés manuellement sans utiliser l'échappement vertabim.
C'est à dire. Le regex devrait être ceci en utilisant des échappements manuels:
",(?=(?:[^\"\"]*\"\"[^\"\"]*\"\")*(?![^\"\"]*\"\"))"
ce qui se traduit par
",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"
Lorsque vous utilisez une chaîne vertabim,
@",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"
elle se comporte comme suit, comme vous pouvez le voir si vous déboguez l'expression régulière:Donc en résumé, je recommande la solution de harpo, mais attention à ce petit piège!
J'ai inclus dans le CsvReader un petit coffre-fort facultatif pour vous informer si cette erreur se produit (si vous avez un nombre pré-connu de colonnes):
Cela peut être injecté via le constructeur:
la source
[^""]
la même chose que[^"]
? La duplication d'un caractère dans une spécification de classe de caractères est redondante, non?Ajoutez une référence à Microsoft.VisualBasic (oui, il dit VisualBasic mais cela fonctionne aussi bien en C # - rappelez-vous qu'à la fin, tout est juste IL).
Utilisez la
Microsoft.VisualBasic.FileIO.TextFieldParser
classe pour analyser le fichier CSV Voici l'exemple de code:la source
parser.HasFieldsEnclosedInQuotes = true;
et le fichier d'entrée devrait inclure des champs contenant des virgules entre guillemets selon la spécification CSV - Excel le fait déjà.Vous pouvez utiliser des "délimiteurs" alternatifs comme ";" ou "|" mais le plus simple pourrait simplement être de citer ce qui est pris en charge par la plupart des bibliothèques CSV (décentes) et les feuilles de calcul les plus décentes.
Pour plus d'informations sur les délimiteurs CSV et une spécification pour un format standard pour décrire les délimiteurs et les citations, voir cette page Web
la source
Si vous êtes sur un nix-système * , avoir accès à
sed
et il peut y avoir un ou plusieurs virgules indésirables que dans un champ spécifique de votre CSV, vous pouvez utiliser la seule ligne suivante afin de les enfermer dans"
de RFC4180 Section 2 propose:Selon le champ dans lequel les virgules indésirables peuvent se trouver, vous devez modifier / étendre les groupes de capture de l'expression régulière (et la substitution).
L'exemple ci-dessus mettra le quatrième champ (sur six) entre guillemets.
En combinaison avec l'
--in-place
option vous pouvez appliquer ces modifications directement au fichier.Afin de "construire" la bonne expression rationnelle, il y a un principe simple à suivre:
[^,]*,
et les rassemblez tous dans un groupe de capture.(.*)
.,.*
et les rassemblez tous dans un groupe de capture.Voici un bref aperçu des différentes expressions rationnelles / substitutions possibles en fonction du domaine spécifique. Sinon, la substitution est
\1"\2"\3
.Si vous souhaitez supprimer les virgules indésirables au
sed
lieu de les entourer de guillemets, reportez-vous à cette réponse .la source
Si vous avez envie de réinventer la roue, les éléments suivants peuvent vous convenir:
la source
En Europe, nous avons ce problème doit plus tôt que cette question. En Europe, nous utilisons tous une virgule pour un point décimal. Voir ces chiffres ci-dessous:
Il n'est donc pas possible d'utiliser le séparateur de virgules pour les fichiers CSV. Pour cette raison, les fichiers CSV en Europe sont séparés par un point-virgule (
;
) .Des programmes comme Microsoft Excel peuvent lire des fichiers avec un point-virgule et il est possible de passer du séparateur. Vous pouvez même utiliser un onglet (
\t
) comme séparateur. Voir cette réponse de Supper User .la source
Si vous êtes intéressé par un exercice plus éducatif sur la façon d'analyser les fichiers en général (en utilisant CSV comme exemple), vous pouvez consulter cet article de Julian Bucknall. J'aime l'article parce qu'il décompose les choses en problèmes beaucoup plus petits et beaucoup moins insurmontables. Vous créez d'abord une grammaire, et une fois que vous avez une bonne grammaire, c'est un processus relativement simple et méthodique pour convertir la grammaire en code.
L'article utilise C # et a un lien en bas pour télécharger le code.
la source
Voici une petite solution de contournement intéressante:
Vous pouvez utiliser un signe de chiffre inférieur grec à la place (U + 0375)
Ça ressemble à ça ͵
L'utilisation de cette méthode vous permet également d'économiser beaucoup de ressources ...
la source
Utilisez simplement SoftCircuits.CsvParser sur NuGet. Il gérera tous ces détails pour vous et gère efficacement les très gros fichiers. Et, si nécessaire, il peut même importer / exporter des objets en mappant les colonnes aux propriétés des objets. De plus, mes tests ont montré qu'il était en moyenne près de 4 fois plus rapide que le populaire CsvHelper.
la source
Comme il s'agit de pratiques générales, commençons par les règles générales:
N'utilisez pas CSV, utilisez XML avec une bibliothèque pour lire et écrire le fichier xml à la place.
Si vous devez utiliser CSV. Faites-le correctement et utilisez une bibliothèque gratuite pour analyser et stocker les fichiers CSV.
Pour justifier 1), la plupart des analyseurs CSV ne connaissent pas le codage, donc si vous ne traitez pas avec US-ASCII, vous demandez des problèmes. Par exemple, Excel 2002 stocke le CSV dans le codage local sans aucune note sur le codage. La norme CSV n'est pas largement adoptée :(. En revanche, la norme xml est bien adoptée et elle gère assez bien les encodages.
Pour justifier 2), il y a des tonnes d'analyseurs csv pour presque toutes les langues, il n'est donc pas nécessaire de réinventer la roue même si les solutions semblent assez simples.
Pour n'en nommer que quelques-uns:
pour python, utilisez la construction dans le module csv
pour perl vérifier CPAN et Text :: CSV
pour php, utilisez les fonctions fgetcsv / fputcsv
pour la bibliothèque Java SuperCVS
Il n'est vraiment pas nécessaire de l'implémenter à la main si vous n'allez pas l'analyser sur un périphérique intégré.
la source
Vous pouvez lire le fichier csv comme ceci.
cela utilise des divisions et prend soin des espaces.
la source
Tout d'abord, posons-nous la question: "Pourquoi ressentons-nous le besoin de gérer les virgules différemment pour les fichiers CSV?"
Pour moi, la réponse est: "Parce que lorsque j'exporte des données dans un fichier CSV, les virgules dans un champ disparaissent et mon champ est séparé en plusieurs champs où les virgules apparaissent dans les données d'origine." (C'est parce que la virgule est le caractère séparateur de champ CSV.)
Selon votre situation, des points-virgules peuvent également être utilisés comme séparateurs de champ CSV.
Compte tenu de mes besoins, je peux utiliser un caractère, par exemple, un guillemet simple bas 9, qui ressemble à une virgule.
Alors, voici comment vous pouvez le faire dans Go:
Le deuxième caractère à virgule dans la fonction Remplacer est décimal 8218.
Sachez que si vous avez des clients qui peuvent avoir des lecteurs de texte ascii uniquement, ce caractère decima 8218 ne ressemblera pas à une virgule. Si tel est votre cas, je vous recommande de entourer le champ de virgule (ou point-virgule) avec des guillemets doubles selon RFC 4128: https://tools.ietf.org/html/rfc4180
la source
J'encode généralement par URL les champs qui peuvent avoir des virgules ou des caractères spéciaux. Et puis le décoder lorsqu'il est utilisé / affiché sur n'importe quel support visuel.
(les virgules deviennent% 2C)
Chaque langue devrait avoir des méthodes pour encoder et décoder les chaînes URL.
par exemple, en java
Je sais que c'est une solution très générale et qu'elle pourrait ne pas être idéale pour les situations où l'utilisateur souhaite afficher manuellement le contenu du fichier csv.
la source
Je fais généralement cela dans mes routines d'analyse de fichiers CSV. Supposons que la variable «ligne» soit une ligne dans un fichier CSV et que toutes les valeurs des colonnes soient placées entre guillemets. Après l'exécution des deux lignes ci-dessous, vous obtiendrez des colonnes CSV dans la collection «values».
la source
La solution la plus simple que j'ai trouvée est celle que LibreOffice utilise:
"
par”
Vous pouvez également utiliser celui qu'Excel utilise:
"
par""
Remarquez que d'autres personnes ont recommandé de ne faire que l'étape 2 ci-dessus, mais cela ne fonctionne pas avec les lignes où a
"
est suivi de a,
, comme dans un CSV où vous voulez avoir une seule colonne avec la chaînehello",world
, comme le CSV le lirait:Qui est interprété comme une ligne avec deux colonnes:
hello
etworld"
la source
hello",world
champ devrait simplement être enregistré sous"hello"",world"
, qui peut être analysé correctement à 100%.la source
J'ai utilisé la bibliothèque Csvreader mais en utilisant cela, j'ai obtenu des données en explosant à partir de la virgule (,) dans la valeur de la colonne.
Donc, si vous souhaitez insérer des données de fichier CSV contenant des virgules (,) dans la plupart des valeurs des colonnes, vous pouvez utiliser la fonction ci-dessous. Lien auteur => https://gist.github.com/jaywilliams/385876
la source
J'ai utilisé la bibliothèque papaParse pour analyser le fichier CSV et avoir les paires clé-valeur (clé / en-tête / première ligne de la valeur du fichier CSV).
voici un exemple que j'utilise:
https://codesandbox.io/embed/llqmrp96pm
il contient un fichier dummy.csv pour avoir la démo d'analyse CSV.
Je l'ai utilisé dans reactJS bien qu'il soit facile et simple à reproduire dans une application écrite dans n'importe quelle langue.
la source
Un exemple peut aider à montrer comment les virgules peuvent être affichées dans un fichier .csv. Créez un fichier texte simple comme suit:
Enregistrez ce fichier texte en tant que fichier texte avec le suffixe ".csv" et ouvrez-le avec Excel 2000 à partir de Windows 10.
aa, bb, cc, d; d "Dans la présentation de la feuille de calcul, la ligne ci-dessous doit ressembler à la ligne ci-dessus, sauf que ci-dessous montre une virgule affichée au lieu d'un point-virgule entre les d." aa, bb, cc, "d, d", cela fonctionne même dans Excel
aa, bb, cc, "d, d", Cela fonctionne même dans Excel 2000 aa, bb, cc, "d, d", Cela fonctionne même dans Excel 2000 aa, bb, cc, "d, d", Cela fonctionne même dans Excel 2000
aa, bb, cc, "d, d", cela échoue dans Excel 2000 en raison de l'espace belore la 1ère citation aa, bb, cc, "d, d", cela échoue dans Excel 2000 en raison de l'espace belore la 1ère citation aa, bb, cc, "d, d", cela échoue dans Excel 2000 en raison de l'espace bélier la 1ère citation
aa, bb, cc, "d, d", Cela fonctionne même dans Excel 2000 même avec des espaces avant et après le 2ème devis. aa, bb, cc, "d, d", Cela fonctionne même dans Excel 2000 même avec des espaces avant et après le 2ème devis. aa, bb, cc, "d, d", Cela fonctionne même dans Excel 2000 même avec des espaces avant et après le 2ème devis.
Règle: Si vous souhaitez afficher une virgule dans une cellule (champ) d'un fichier .csv: "Commencez et terminez le champ par des guillemets doubles, mais évitez les espaces blancs avant le premier devis"
la source
Je pense que la solution la plus simple à ce problème est d'avoir le client pour ouvrir le csv dans Excel, puis ctrl + r pour remplacer toutes les virgules par l'identifiant que vous voulez. Ceci est très simple pour le client et ne nécessite qu'une seule modification de votre code pour lire le délimiteur de votre choix.
la source
Utilisez un caractère de tabulation (\ t) pour séparer les champs.
la source