Étant donné que cela a été créé un an plus tôt que 1103495, je pense que cette question est un double de celle-ci.
MattH
2
Merci, Matt. J'essayais juste de les relier, pas d'indiquer lequel est venu en premier. Vous verrez que j'ai exactement le même texte sur l'autre question qui pointe vers celle-ci. Y a-t-il une meilleure façon de lier deux questions ensemble?
TextFieldParser de Microsoft est stable et suit la RFC 4180 pour les fichiers CSV. Ne soyez pas rebuté par l' Microsoft.VisualBasicespace de noms; c'est un composant standard dans le .NET Framework, ajoutez simplement une référence à l' Microsoft.VisualBasicassembly global .
Si vous compilez pour Windows (par opposition à Mono) et que vous ne prévoyez pas d'analyser des fichiers CSV «cassés» (non conformes à la RFC), alors ce serait le choix évident, car il est gratuit, sans restriction, stable, et activement pris en charge, dont la plupart ne peut pas être dit pour FileHelpers.
Il n'y a en fait rien de spécifique à VB à propos de cette classe autre que son espace de noms malheureusement nommé. Je choisirais certainement cette bibliothèque si je n'avais besoin que d'un analyseur CSV «simple», car il n'y a rien à télécharger, distribuer ou à craindre en général. À cette fin, j'ai édité la formulation axée sur le VB de cette réponse.
Aaronaught
@Aaronaught Je pense que vos modifications sont principalement une amélioration. Bien que cette RFC ne fasse pas nécessairement autorité, comme de nombreux rédacteurs CSV ne la respectent pas, par exemple, Excel n'utilise pas toujours une virgule dans les fichiers "CSV". Ma réponse précédente ne disait-elle pas non plus que la classe pouvait être utilisée à partir de C #?
MarkJ
La TextFieldParservolonté de travail délimité par des tabulations et d' autres étranges cruft généré Excel aussi. Je me rends compte que votre réponse précédente ne prétendait pas que la bibliothèque était spécifique à VB, elle m'est juste apparue comme impliquant qu'elle était vraiment destinée à VB, et non destinée à être utilisée à partir de C #, ce que je ne pense pas le cas - il existe des classes vraiment utiles dans MSVB.
Cela nécessite un accès au système de fichiers. Pour autant que je sache, il n'y a aucun moyen de faire fonctionner OLEDB avec des flux en mémoire :(
UserControl
3
@UserControl, bien sûr, il nécessite un accès au système de fichiers. Il a posé une question sur l'importation d'un fichier CSV
Kevin
1
Je ne me plains pas. En fait, je préférerais la solution OLEDB au reste, mais j'étais frustré tant de fois lorsque je devais analyser le CSV dans les applications ASP.NET, je voulais donc le noter.
UserControl
12
Si vous vous attendez à des scénarios assez complexes pour l'analyse CSV, ne pensez même pas à lancer notre propre analyseur . Il existe de nombreux excellents outils, comme FileHelpers , ou même ceux de CodeProject .
Le fait est que c'est un problème assez courant et vous pouvez parier que de nombreux développeurs de logiciels ont déjà pensé et résolu ce problème.
Bien que ce lien puisse répondre à la question, il est préférable d'inclure les parties essentielles de la réponse ici et de fournir le lien pour référence. Les réponses aux liens uniquement peuvent devenir invalides si la page liée change. - De l'avis
techspider
Merci @techspider J'espère que vous avez noté que cet article provenait de la période bêta de StackOverflow: D Cela étant dit, de nos jours, les outils CSV proviennent mieux des packages Nuget - donc je ne suis pas sûr que même les réponses de lien soient à l'abri de 8 ans -anciens cycles d'évolution de la technologie
Jon Limjap
9
Brian donne une belle solution pour le convertir en une collection fortement typée.
La plupart des méthodes d'analyse CSV données ne prennent pas en compte les champs d'échappement ou certaines des autres subtilités des fichiers CSV (comme le découpage des champs). Voici le code que j'utilise personnellement. C'est un peu rugueux sur les bords et il n'y a pratiquement pas de rapport d'erreur.
publicstaticIList<IList<string>>Parse(string content){IList<IList<string>> records =newList<IList<string>>();StringReader stringReader =newStringReader(content);bool inQoutedString =false;IList<string> record =newList<string>();StringBuilder fieldBuilder =newStringBuilder();while(stringReader.Peek()!=-1){char readChar =(char)stringReader.Read();if(readChar =='\n'||(readChar =='\r'&& stringReader.Peek()=='\n')){// If it's a \r\n combo consume the \n part and throw it away.if(readChar =='\r'){
stringReader.Read();}if(inQoutedString){if(readChar =='\r'){
fieldBuilder.Append('\r');}
fieldBuilder.Append('\n');}else{
record.Add(fieldBuilder.ToString().TrimEnd());
fieldBuilder =newStringBuilder();
records.Add(record);
record =newList<string>();
inQoutedString =false;}}elseif(fieldBuilder.Length==0&&!inQoutedString){if(char.IsWhiteSpace(readChar)){// Ignore leading whitespace}elseif(readChar =='"'){
inQoutedString =true;}elseif(readChar ==','){
record.Add(fieldBuilder.ToString().TrimEnd());
fieldBuilder =newStringBuilder();}else{
fieldBuilder.Append(readChar);}}elseif(readChar ==','){if(inQoutedString){
fieldBuilder.Append(',');}else{
record.Add(fieldBuilder.ToString().TrimEnd());
fieldBuilder =newStringBuilder();}}elseif(readChar =='"'){if(inQoutedString){if(stringReader.Peek()=='"'){
stringReader.Read();
fieldBuilder.Append('"');}else{
inQoutedString =false;}}else{
fieldBuilder.Append(readChar);}}else{
fieldBuilder.Append(readChar);}}
record.Add(fieldBuilder.ToString().TrimEnd());
records.Add(record);return records;}
Notez que cela ne gère pas la casse de bord des champs qui ne sont pas délimités par des guillemets doubles, mais meerley ayant une chaîne entre guillemets à l'intérieur. Voir cet article pour une meilleure explication ainsi que des liens vers certaines bibliothèques appropriées.
Je suis d'accord avec @ NotMyself . FileHelpers est bien testé et gère toutes sortes de cas que vous devrez éventuellement gérer si vous le faites vous-même. Jetez un œil à ce que fait FileHelpers et n'écrivez les vôtres que si vous êtes absolument sûr que (1) vous n'aurez jamais besoin de gérer les cas extrêmes que FileHelpers fait, ou (2) vous aimez écrire ce genre de choses et allez soyez ravi lorsque vous devez analyser des choses comme celle-ci:
1, "Bill", "Smith", "Supervisor", "No Comment"
2, «Drake», «O'Malley», «Concierge,
Oups, je ne suis pas cité et je suis sur une nouvelle ligne!
Je m'ennuyais donc j'ai modifié certaines choses que j'ai écrites. Il essaie d'encapsuler l'analyse d'une manière OO tout en réduisant le nombre d'itérations dans le fichier, il n'itère qu'une fois en haut pour chacun.
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.IO;namespaceConsoleApplication1{classProgram{staticvoidMain(string[] args){// usage:// note this wont run as getting streams is not Implemented// but will get you startedCSVFileParser fileParser =newCSVFileParser();// TO Do: configure fileparserPersonParser personParser =newPersonParser(fileParser);List<Person> persons =newList<Person>();// if the file is large and there is a good way to limit// without having to reparse the whole file you can use a // linq query if you desireforeach(Person person in personParser.GetPersons()){
persons.Add(person);}// now we have a list of Person objects}}publicabstractclassCSVParser{protectedString[] deliniators ={","};protectedinternalIEnumerable<String[]>GetRecords(){Stream stream =GetStream();StreamReader reader =newStreamReader(stream);String[] aRecord;while(!reader.EndOfStream){
aRecord = reader.ReadLine().Split(deliniators,StringSplitOptions.None);yieldreturn aRecord;}}protectedabstractStreamGetStream();}publicclassCSVFileParser:CSVParser{// to do: add logic to get a stream from a fileprotectedoverrideStreamGetStream(){thrownewNotImplementedException();}}publicclassCSVWebParser:CSVParser{// to do: add logic to get a stream from a web requestprotectedoverrideStreamGetStream(){thrownewNotImplementedException();}}publicclassPerson{publicStringName{get;set;}publicStringAddress{get;set;}publicDateTime DOB {get;set;}}publicclassPersonParser{publicPersonParser(CSVParser parser){this.Parser= parser;}publicCSVParserParser{get;set;}publicIEnumerable<Person>GetPersons(){foreach(String[] record inthis.Parser.GetRecords()){yieldreturnnewPerson(){Name= record[0],Address= record[1],
DOB =DateTime.Parse(record[2]),};}}}}
Un bon moyen simple de le faire est d'ouvrir le fichier et de lire chaque ligne dans un tableau, une liste chaînée, une structure de données de votre choix. Soyez prudent lorsque vous manipulez la première ligne.
C'est peut-être au-dessus de votre tête, mais il semble y avoir un moyen direct d'y accéder également en utilisant une chaîne de connexion .
Pourquoi ne pas essayer d'utiliser Python au lieu de C # ou VB? Il a un joli module CSV à importer qui fait tout le gros du travail pour vous.
Ne passez pas à python depuis VB pour le plaisir d'un analyseur CSV. Il y en a un dans VB. Bien que bizarrement, il semble avoir été ignoré dans les réponses à cette question. msdn.microsoft.com/en-us/library/...
MarkJ
1
J'ai dû utiliser un analyseur CSV en .NET pour un projet cet été et me suis installé sur le pilote Microsoft Jet Text. Vous spécifiez un dossier à l'aide d'une chaîne de connexion, puis interrogez un fichier à l'aide d'une instruction SQL Select. Vous pouvez spécifier des types forts à l'aide d'un fichier schema.ini. Je ne l'ai pas fait au début, mais j'obtenais de mauvais résultats là où le type de données n'était pas immédiatement apparent, comme les numéros IP ou une entrée comme "XYQ 3.9 SP1".
Une limitation que j'ai rencontrée est qu'il ne peut pas gérer les noms de colonnes au-dessus de 64 caractères; il tronque. Cela ne devrait pas être un problème, sauf que j'avais affaire à des données d'entrée très mal conçues. Il renvoie un DataSet ADO.NET.
C'était la meilleure solution que j'ai trouvée. Je me méfierais de lancer mon propre analyseur CSV, car je manquerais probablement certains des cas de fin, et je n'ai trouvé aucun autre package d'analyse CSV gratuit pour .NET.
EDIT: De plus, il ne peut y avoir qu'un seul fichier schema.ini par répertoire, je l'ai donc ajouté dynamiquement pour taper fortement les colonnes nécessaires. Il ne tapera fortement que les colonnes spécifiées et en déduira pour tout champ non spécifié. J'ai vraiment apprécié cela, car je travaillais à importer un fichier CSV fluide de plus de 70 colonnes et je ne voulais pas spécifier chaque colonne, uniquement celles qui se comportaient mal.
Il existe peut-être des bibliothèques que vous pourriez utiliser pour vous aider, mais c'est probablement aussi simple que possible. Assurez-vous simplement que vous ne pouvez pas avoir de virgules dans les données, sinon vous devrez mieux les analyser.
très mauvais sur l'utilisation de la mémoire et beaucoup de frais généraux. Petit devrait être moins grâce à quelques kilo-octets. Certainement pas bon pour un csv de 10 Mo!
Piotr Kula
Cela dépend de la taille de votre mémoire et du fichier.
Réponses:
TextFieldParser de Microsoft est stable et suit la RFC 4180 pour les fichiers CSV. Ne soyez pas rebuté par l'
Microsoft.VisualBasic
espace de noms; c'est un composant standard dans le .NET Framework, ajoutez simplement une référence à l'Microsoft.VisualBasic
assembly global .Si vous compilez pour Windows (par opposition à Mono) et que vous ne prévoyez pas d'analyser des fichiers CSV «cassés» (non conformes à la RFC), alors ce serait le choix évident, car il est gratuit, sans restriction, stable, et activement pris en charge, dont la plupart ne peut pas être dit pour FileHelpers.
Voir aussi: Comment: lire des fichiers texte délimités par des virgules dans Visual Basic pour un exemple de code VB.
la source
TextFieldParser
volonté de travail délimité par des tabulations et d' autres étranges cruft généré Excel aussi. Je me rends compte que votre réponse précédente ne prétendait pas que la bibliothèque était spécifique à VB, elle m'est juste apparue comme impliquant qu'elle était vraiment destinée à VB, et non destinée à être utilisée à partir de C #, ce que je ne pense pas le cas - il existe des classes vraiment utiles dans MSVB.Utilisez une connexion OleDB.
la source
Si vous vous attendez à des scénarios assez complexes pour l'analyse CSV, ne pensez même pas à lancer notre propre analyseur . Il existe de nombreux excellents outils, comme FileHelpers , ou même ceux de CodeProject .
Le fait est que c'est un problème assez courant et vous pouvez parier que de nombreux développeurs de logiciels ont déjà pensé et résolu ce problème.
la source
Brian donne une belle solution pour le convertir en une collection fortement typée.
La plupart des méthodes d'analyse CSV données ne prennent pas en compte les champs d'échappement ou certaines des autres subtilités des fichiers CSV (comme le découpage des champs). Voici le code que j'utilise personnellement. C'est un peu rugueux sur les bords et il n'y a pratiquement pas de rapport d'erreur.
Notez que cela ne gère pas la casse de bord des champs qui ne sont pas délimités par des guillemets doubles, mais meerley ayant une chaîne entre guillemets à l'intérieur. Voir cet article pour une meilleure explication ainsi que des liens vers certaines bibliothèques appropriées.
la source
Je suis d'accord avec @ NotMyself . FileHelpers est bien testé et gère toutes sortes de cas que vous devrez éventuellement gérer si vous le faites vous-même. Jetez un œil à ce que fait FileHelpers et n'écrivez les vôtres que si vous êtes absolument sûr que (1) vous n'aurez jamais besoin de gérer les cas extrêmes que FileHelpers fait, ou (2) vous aimez écrire ce genre de choses et allez soyez ravi lorsque vous devez analyser des choses comme celle-ci:
1, "Bill", "Smith", "Supervisor", "No Comment"
2, «Drake», «O'Malley», «Concierge,
Oups, je ne suis pas cité et je suis sur une nouvelle ligne!
la source
Je m'ennuyais donc j'ai modifié certaines choses que j'ai écrites. Il essaie d'encapsuler l'analyse d'une manière OO tout en réduisant le nombre d'itérations dans le fichier, il n'itère qu'une fois en haut pour chacun.
la source
Il existe deux articles sur CodeProject qui fournissent du code pour une solution, un qui utilise StreamReader et un qui importe des données CSV à l'aide du pilote de texte Microsoft .
la source
Un bon moyen simple de le faire est d'ouvrir le fichier et de lire chaque ligne dans un tableau, une liste chaînée, une structure de données de votre choix. Soyez prudent lorsque vous manipulez la première ligne.
C'est peut-être au-dessus de votre tête, mais il semble y avoir un moyen direct d'y accéder également en utilisant une chaîne de connexion .
Pourquoi ne pas essayer d'utiliser Python au lieu de C # ou VB? Il a un joli module CSV à importer qui fait tout le gros du travail pour vous.
la source
J'ai dû utiliser un analyseur CSV en .NET pour un projet cet été et me suis installé sur le pilote Microsoft Jet Text. Vous spécifiez un dossier à l'aide d'une chaîne de connexion, puis interrogez un fichier à l'aide d'une instruction SQL Select. Vous pouvez spécifier des types forts à l'aide d'un fichier schema.ini. Je ne l'ai pas fait au début, mais j'obtenais de mauvais résultats là où le type de données n'était pas immédiatement apparent, comme les numéros IP ou une entrée comme "XYQ 3.9 SP1".
Une limitation que j'ai rencontrée est qu'il ne peut pas gérer les noms de colonnes au-dessus de 64 caractères; il tronque. Cela ne devrait pas être un problème, sauf que j'avais affaire à des données d'entrée très mal conçues. Il renvoie un DataSet ADO.NET.
C'était la meilleure solution que j'ai trouvée. Je me méfierais de lancer mon propre analyseur CSV, car je manquerais probablement certains des cas de fin, et je n'ai trouvé aucun autre package d'analyse CSV gratuit pour .NET.
EDIT: De plus, il ne peut y avoir qu'un seul fichier schema.ini par répertoire, je l'ai donc ajouté dynamiquement pour taper fortement les colonnes nécessaires. Il ne tapera fortement que les colonnes spécifiées et en déduira pour tout champ non spécifié. J'ai vraiment apprécié cela, car je travaillais à importer un fichier CSV fluide de plus de 70 colonnes et je ne voulais pas spécifier chaque colonne, uniquement celles qui se comportaient mal.
la source
J'ai tapé du code. Le résultat dans le datagridviewer semblait bon. Il analyse une seule ligne de texte en une liste d'objets.
la source
Si vous pouvez garantir qu'il n'y a pas de virgule dans les données, le moyen le plus simple serait probablement d'utiliser String.split .
Par exemple:
Il existe peut-être des bibliothèques que vous pourriez utiliser pour vous aider, mais c'est probablement aussi simple que possible. Assurez-vous simplement que vous ne pouvez pas avoir de virgules dans les données, sinon vous devrez mieux les analyser.
la source