In der Tat ausgezeichnet. Es funktionierte sofort perfekt für mich, ohne die Dokumentation zu lesen.
Grinsender
Funktioniert dies bei CSV-Dateien, bei denen jede Zeile eine andere Struktur haben kann? Ich habe eine Protokolldatei mit verschiedenen Arten von protokollierten Ereignissen, die in mehrere Tabellen aufgeteilt werden müssten.
Gonzobrains
2
@gonzobrains - Wahrscheinlich nicht; Die Grundannahme einer CSV-Datei ist eine rechteckige Datenstruktur, die auf einem einzelnen Satz von Spaltenüberschriften basiert, die in der ersten Zeile angegeben sind. Was Sie haben, scheinen allgemeinere, durch Kommas getrennte, diskriminierte Daten zu sein, die eine komplexere "ETL" erfordern, um aus der Datei in Objektinstanzen unterschiedlichen Typs zu analysieren (einschließlich DataRows verschiedener DataTables).
KeithS
93
Ich habe OleDbAnbieter verwendet. Es gibt jedoch Probleme, wenn Sie Zeilen mit numerischen Werten lesen, diese jedoch als Text behandeln möchten. Sie können dieses Problem jedoch umgehen, indem Sie eine schema.iniDatei erstellen. Hier ist meine Methode, die ich verwendet habe:
// using System.Data;// using System.Data.OleDb;// using System.Globalization;// using System.IO;staticDataTableGetDataTableFromCsv(string path,bool isFirstRowHeader){string header = isFirstRowHeader ?"Yes":"No";string pathOnly =Path.GetDirectoryName(path);string fileName =Path.GetFileName(path);string sql =@"SELECT * FROM ["+ fileName +"]";
using(OleDbConnection connection =newOleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+ pathOnly +";Extended Properties=\"Text;HDR="+ header +"\""))
using(OleDbCommand command =newOleDbCommand(sql, connection))
using(OleDbDataAdapter adapter =newOleDbDataAdapter(command)){DataTable dataTable =newDataTable();
dataTable.Locale=CultureInfo.CurrentCulture;
adapter.Fill(dataTable);return dataTable;}}
Danke Kumpel. Das hat mir geholfen. Ich hatte eine CSV-Datei, in der Kommas nicht nur Trennzeichen waren, sondern sich überall in vielen Spaltenwerten befanden. Daher war es eine Herausforderung, einen regulären Ausdruck zu finden, der die Zeile aufteilt. Der OleDbProvider hat das Schema korrekt abgeleitet.
Galilyou
Die Implementierung ist sinnvoll, aber wie gehen wir mit Zellen um, die gemischte Datentypen enthalten? Zum Beispiel 40C und etc.?
GKED
GKED: Wenn die Daten, die Sie einlesen, immer einen erwarteten Satz von Spalten und Typen enthalten, können Sie im selben Ordner eine shema.ini-Datei ablegen, die Informationen zum OleDb-Anbieter über die Spalten enthält. Hier ist ein Link zu einem Microsoft-Artikel, der Details zur Strukturierung der Datei enthält. msdn.microsoft.com/en-us/library/…
Jim Scott
4
Obwohl diese Antwort funktionieren wird, würde ich dringend davon abraten. Sie führen eine externe Abhängigkeit ein, die abhängig von den installierten Versionen zu Konflikten mit anderen Office-Installationen auf demselben Computer führen kann (Excel in Ihrer lokalen Entwicklungsumgebung verwenden?). Es gibt NuGet-Pakete (ExcelDataReader, CsvHelper), die dies effizienter und portabler tun.
A. Murray
1
@ A. Murray - Was genau meinst du? Dies verwendet den in System.Data.dll integrierten OleDb-Anbieter. Sie müssen keine zusätzlichen "Treiber" installieren. Und ich wäre heutzutage schockiert, wenn bei einer Windows-Installation nicht der grundlegende Jet-Treiber installiert wäre. Dies ist 1990er CSV ....
Jay Riggs Vorschlag ist auch eine großartige Lösung, aber ich brauchte einfach nicht alle Funktionen, die das bietet Andrew Rissings Generic Parser bietet.
UPDATE 25.10.2010
Nach dem Gebrauch ich fast anderthalb Jahre lang den CSV-Reader Sebastien Lorion in meinem Projekt verwendet habe, habe ich festgestellt, dass er beim Parsen einiger CSV-Dateien, von denen ich glaube, dass sie gut geformt sind, Ausnahmen auslöst.
var csv =@"Name, Age
Ronnie, 30
Mark, 40
Ace, 50";TextReader reader =newStringReader(csv);var table =newDataTable();
using(var it = reader.ReadCsvWithHeader().GetEnumerator()){if(!it.MoveNext())return;foreach(var k in it.Current.Keys)
table.Columns.Add(k);do{var row = table.NewRow();foreach(var k in it.Current.Keys)
row[k]= it.Current[k];
table.Rows.Add(row);}while(it.MoveNext());}
Ich stimme zu, dass Sebastien Loriens CSV-Leser großartig ist. Ich benutze es für schwere CSV-Verarbeitung, aber ich habe Andrews Rissing's auch für kleine Jobs verwendet und es hat mir gute Dienste geleistet. Habe Spaß!
Jay Riggs
Wie kann ich diese Klassen verwenden, um CSV in DATATABLE zu laden?
Muflix
Ich habe dies versucht, aber die it.Current.Keys-Auflistung wird mit "System.Linq.Enumerable + WhereSelectListIterator`2 [System.Int32, System.Char]" anstelle des Namens der Spalte zurückgegeben. Irgendwelche Gedanken darüber warum?
user3658298
Können Sie Trennzeichen für mehrere Zeichen verwenden?
rollt
Nein, aber ich habe darüber nachgedacht, dies zu ermöglichen.
Ronnie Overby
32
Hey, es funktioniert zu 100%
publicstaticDataTableConvertCSVtoDataTable(string strFilePath){DataTable dt =newDataTable();
using (StreamReader sr =newStreamReader(strFilePath)){string[] headers = sr.ReadLine().Split(',');foreach(string header in headers){
dt.Columns.Add(header);}while(!sr.EndOfStream){string[] rows = sr.ReadLine().Split(',');DataRow dr = dt.NewRow();for(int i =0; i < headers.Length; i++){
dr[i]= rows[i];}
dt.Rows.Add(dr);}}return dt;}
@ ShivamSrivastava Ich bekomme den Fehler in der letzten Zeile Sind Sie da, dann geben Sie andere Kontaktinformationen
Sunil Acharya
Obwohl ich diese Version nicht genau verwendet habe, habe ich daraufhin mein Problem gelöst. Danke dir. Funktioniert sehr gut.
Nrod
13
Wir haben immer den Jet.OLEDB-Treiber verwendet, bis wir zu 64-Bit-Anwendungen gingen. Microsoft hat und wird keinen 64-Bit-Jet-Treiber veröffentlichen. Hier ist eine einfache Lösung, die File.ReadAllLines und String.Split verwendet, um die CSV-Datei zu lesen und zu analysieren und eine DataTable manuell zu laden. Wie oben erwähnt, wird die Situation, in der einer der Spaltenwerte ein Komma enthält, NICHT behandelt. Wir verwenden dies hauptsächlich zum Lesen benutzerdefinierter Konfigurationsdateien. Das Schöne an der Verwendung von CSV-Dateien ist, dass wir sie in Excel bearbeiten können.
stringCSVFilePathName=@"C:\test.csv";string[]Lines=File.ReadAllLines(CSVFilePathName);string[]Fields;Fields=Lines[0].Split(newchar[]{','});intCols=Fields.GetLength(0);DataTable dt =newDataTable();//1st row must be column names; force lower case to ensure matching later on.for(int i =0; i <Cols; i++)
dt.Columns.Add(Fields[i].ToLower(),typeof(string));DataRowRow;for(int i =1; i <Lines.GetLength(0); i++){Fields=Lines[i].Split(newchar[]{','});Row= dt.NewRow();for(int f =0; f <Cols; f++)Row[f]=Fields[f];
dt.Rows.Add(Row);}
Dies ist der Code, den ich benutze, aber Ihre Apps müssen mit Net Version 3.5 ausgeführt werden
privatevoid txtRead_Click(object sender,EventArgs e){// var filename = @"d:\shiptest.txt";
openFileDialog1.InitialDirectory="d:\\";
openFileDialog1.Filter="txt files (*.txt)|*.txt|All files (*.*)|*.*";DialogResult result = openFileDialog1.ShowDialog();if(result ==DialogResult.OK){if(openFileDialog1.FileName!=""){var reader =ReadAsLines(openFileDialog1.FileName);var data =newDataTable();//this assume the first record is filled with the column namesvar headers = reader.First().Split(',');foreach(var header in headers){
data.Columns.Add(header);}var records = reader.Skip(1);foreach(var record in records){
data.Rows.Add(record.Split(','));}
dgList.DataSource= data;}}}staticIEnumerable<string>ReadAsLines(string filename){
using (StreamReader reader =newStreamReader(filename))while(!reader.EndOfStream)yieldreturn reader.ReadLine();}
Ich bin auf diesen Code gestoßen, der Linq und Regex verwendet, um eine CSV-Datei zu analysieren. Der Artikel, auf den verwiesen wird, ist jetzt über anderthalb Jahre alt, hat jedoch keine bessere Möglichkeit gefunden, eine CSV mit Linq (und Regex) zu analysieren. Die Einschränkung ist, dass der hier angewendete reguläre Ausdruck für durch Kommas getrennte Dateien gilt (erkennt Kommas in Anführungszeichen!) Und dass es für Header möglicherweise nicht gut ist, aber es gibt eine Möglichkeit, diese zu überwinden). Nehmen Sie einen Höhepunkt:
Dim lines AsString()=System.IO.File.ReadAllLines(strCustomerFile)Dim pattern AsString=",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"Dim r AsSystem.Text.RegularExpressions.Regex=NewSystem.Text.RegularExpressions.Regex(pattern)Dim custs =From line In lines _
Let data = r.Split(line) _
SelectNewWith{.custnmbr = data(0), _
.custname = data(1)}ForEach cust In custs
strCUSTNMBR =Replace(cust.custnmbr,Chr(34),"")
strCUSTNAME =Replace(cust.custname,Chr(34),"")Next
Die beste Option, die ich gefunden habe und die Probleme behebt, bei denen möglicherweise verschiedene Versionen von Office installiert sind, sowie 32/64-Bit-Probleme, wie sie von Chuck Bevitt erwähnt wurden , sind FileHelpers .
Es kann mit NuGet zu Ihren Projektreferenzen hinzugefügt werden und bietet eine einzeilige Lösung:
Kannst du sagen, was CommonEngine ist? Ist NuGet dasselbe mit NuGet.Core? Ich fand nur NuGet.Core in Referenzen
Sindhu Jampani
Es sind FileHelpers, die Sie brauchen. Wenn Sie NuGet haben, fügen Sie es mit NuGet hinzu. Andernfalls fügen Sie es einfach als Baugruppe in Ihr Projekt ein. CommonEngine ist Teil von FileHelpers.
Neo
3
Für diejenigen unter Ihnen, die keine externe Bibliothek verwenden möchten und OleDB nicht verwenden möchten, siehe das folgende Beispiel. Alles, was ich gefunden habe, war entweder OleDB, eine externe Bibliothek oder einfach das Aufteilen anhand eines Kommas! Für meinen Fall funktionierte OleDB nicht, also wollte ich etwas anderes.
Ich habe einen Artikel von MarkJ gefunden, der auf die hier gezeigte Microsoft.VisualBasic.FileIO.TextFieldParser-Methode verweist . Der Artikel ist in VB geschrieben und gibt keine Datentabelle zurück. Siehe mein Beispiel unten.
publicstaticDataTableLoadCSV(string path,bool hasHeader){DataTable dt =newDataTable();
using (varMyReader=newMicrosoft.VisualBasic.FileIO.TextFieldParser(path)){MyReader.TextFieldType=Microsoft.VisualBasic.FileIO.FieldType.Delimited;MyReader.Delimiters=newString[]{","};string[] currentRow;//'Loop through all of the fields in the file. //'If any lines are corrupt, report an error and continue parsing. bool firstRow =true;while(!MyReader.EndOfData){try{
currentRow =MyReader.ReadFields();//Add the header columnsif(hasHeader && firstRow){foreach(string c in currentRow){
dt.Columns.Add(c,typeof(string));}
firstRow =false;continue;}//Create a new rowDataRow dr = dt.NewRow();
dt.Rows.Add(dr);//Loop thru the current line and fill the data outfor(int c =0; c < currentRow.Count(); c++){
dr[c]= currentRow[c];}}catch(Microsoft.VisualBasic.FileIO.MalformedLineException ex){//Handle the exception here}}}return dt;}
Sehr einfache Antwort: Wenn Sie keine komplexe CSV-Datei haben, die eine einfache Split-Funktion verwenden kann, funktioniert dies gut für den Import (beachten Sie, dass dies als Zeichenfolgen importiert wird, ich mache Datentypkonvertierungen später, wenn ich muss).
privateDataTable csvToDataTable(string fileName,char splitCharacter){StreamReader sr =newStreamReader(fileName);string myStringRow = sr.ReadLine();var rows = myStringRow.Split(splitCharacter);DataTableCsvData=newDataTable();foreach(string column in rows){//creates the columns of new datatable based on first row of csvCsvData.Columns.Add(column);}
myStringRow = sr.ReadLine();while(myStringRow !=null){//runs until string reader returns null and adds rows to dt
rows = myStringRow.Split(splitCharacter);CsvData.Rows.Add(rows);
myStringRow = sr.ReadLine();}
sr.Close();
sr.Dispose();returnCsvData;}
Meine Methode, wenn ich eine Tabelle mit einem String [] -Trennzeichen importiere und das Problem behandle, bei dem die aktuelle Zeile, die ich lese, möglicherweise zur nächsten Zeile in der CSV- oder Textdatei <- gegangen ist. In diesem Fall möchte ich eine Schleife ausführen, bis ich sie erhalte auf die Gesamtzahl der Zeilen in der ersten Zeile (Spalten)
publicstaticDataTableImportCSV(string fullPath,string[] sepString){DataTable dt =newDataTable();
using (StreamReader sr =newStreamReader(fullPath)){//stream uses using statement because it implements iDisposablestring firstLine = sr.ReadLine();var headers = firstLine.Split(sepString,StringSplitOptions.None);foreach(var header in headers){//create column headers
dt.Columns.Add(header);}int columnInterval = headers.Count();string newLine = sr.ReadLine();while(newLine !=null){//loop adds each row to the datatablevar fields = newLine.Split(sepString,StringSplitOptions.None);// csv delimiter var currentLength = fields.Count();if(currentLength < columnInterval){while(currentLength < columnInterval){//if the count of items in the row is less than the column row go to next line until count matches column number total
newLine += sr.ReadLine();
currentLength = newLine.Split(sepString,StringSplitOptions.None).Count();}
fields = newLine.Split(sepString,StringSplitOptions.None);}if(currentLength > columnInterval){//ideally never executes - but if csv row has too many separators, line is skipped
newLine = sr.ReadLine();continue;}
dt.Rows.Add(fields);
newLine = sr.ReadLine();}
sr.Close();}return dt;}
Schön, dass Sie Zeilen noch nicht als Zeichenfolge [] deklariert haben.
Animal Style
@ TierStyle Sie haben Recht - aktualisiert mit robusterer Methode und deklarierten Zeilen
Matt Farguson
3
Geändert von Herrn ChuckBevitt
Arbeitslösung:
stringCSVFilePathName= APP_PATH +"Facilities.csv";string[]Lines=File.ReadAllLines(CSVFilePathName);string[]Fields;Fields=Lines[0].Split(newchar[]{','});intCols=Fields.GetLength(0);DataTable dt =newDataTable();//1st row must be column names; force lower case to ensure matching later on.for(int i =0; i <Cols-1; i++)
dt.Columns.Add(Fields[i].ToLower(),typeof(string));DataRowRow;for(int i =0; i <Lines.GetLength(0)-1; i++){Fields=Lines[i].Split(newchar[]{','});Row= dt.NewRow();for(int f =0; f <Cols-1; f++)Row[f]=Fields[f];
dt.Rows.Add(Row);}
Das löst also ein Speicherproblem, oder? Dies ist eine zeilenweise Verarbeitung, die nicht im Speicher verbleibt, sodass es keine Ausnahmen geben sollte. Ich mag die Art und Weise, wie dies verarbeitet wird, aber speichert File.ReadAllLines () nicht alles im Speicher? Ich denke, Sie sollten File.ReadLines () verwenden, um großen Speicherpuffer zu vermeiden? Dies ist eine gute Antwort auf die vorliegende Frage, die ich nur über Speicherprobleme wissen möchte.
DtechNet
2
Hier ist eine Lösung, die den ODBC-Texttreiber von ADO.Net verwendet:
Dim csvFileFolder AsString="C:\YourFileFolder"Dim csvFileName AsString="YourFile.csv"'Note that the folder is specified in the connection string,'not the file. That's specified in the SELECT query, later.Dim connString AsString="Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq=" _
& csvFileFolder &";Extended Properties=""Text;HDR=No;FMT=Delimited"""Dim conn AsNewOdbc.OdbcConnection(connString)'Open a data adapter, specifying the file name to load
Dim da AsNewOdbc.OdbcDataAdapter("SELECT * FROM ["& csvFileName &"]", conn)'Then fill a data table, which can be bound to a grid
Dim dt AsNewDataTableda.Fill(dt)
grdCSVData.DataSource= dt
Nach dem Ausfüllen können Sie Eigenschaften der Datentabelle wie ColumnName bewerten, um alle Funktionen der ADO.Net-Datenobjekte zu nutzen.
In VS2008 können Sie Linq verwenden, um den gleichen Effekt zu erzielen.
HINWEIS: Dies kann ein Duplikat dieser SO-Frage sein.
Ich kann nicht widerstehen, meinen eigenen Dreh hinzuzufügen. Das ist so viel besser und kompakter als das, was ich in der Vergangenheit verwendet habe.
Diese Lösung:
Hängt nicht von einem Datenbanktreiber oder einer Bibliothek eines Drittanbieters ab.
Schlägt nicht bei doppelten Spaltennamen fehl
Behandelt Kommas in den Daten
Behandelt alle Trennzeichen, nicht nur Kommas (obwohl dies die Standardeinstellung ist).
privatestaticDataTableLoadCsvData(string refPath){var cfg =newConfiguration(){Delimiter=",",HasHeaderRecord=true};var result =newDataTable();
using (var sr =newStreamReader(refPath,Encoding.UTF8,false,16384*2)){
using (var rdr =newCsvReader(sr, cfg))
using (var dataRdr =newCsvDataReader(rdr)){
result.Load(dataRdr);}}return result;}
Beachten Sie, dass in Version 13Configuration umbenannt wurde CsvConfiguration, um Namespace-Konflikte zu vermeiden. Demo dieser Antwort funktioniert: dotnetfiddle.net/sdwc6i
dbc
2
Ich benutze eine Bibliothek namens ExcelDataReader, die Sie auf NuGet finden können. Stellen Sie sicher, dass Sie sowohl ExcelDataReader als auch die Erweiterung ExcelDataReader.DataSet installieren (letztere bietet die erforderliche AsDataSet-Methode, auf die unten verwiesen wird).
Ich habe alles in einer Funktion zusammengefasst, Sie können es direkt in Ihren Code kopieren. Geben Sie einen Pfad zur CSV-Datei ein. Sie erhalten einen Datensatz mit einer Tabelle.
publicstaticDataSetGetDataSet(string filepath){var stream =File.OpenRead(filepath);try{var reader =ExcelReaderFactory.CreateCsvReader(stream,newExcelReaderConfiguration(){LeaveOpen=false});var result = reader.AsDataSet(newExcelDataSetConfiguration(){// Gets or sets a value indicating whether to set the DataColumn.DataType // property in a second pass.UseColumnDataType=true,// Gets or sets a callback to determine whether to include the current sheet// in the DataSet. Called once per sheet before ConfigureDataTable.FilterSheet=(tableReader, sheetIndex)=>true,// Gets or sets a callback to obtain configuration options for a DataTable. ConfigureDataTable=(tableReader)=>newExcelDataTableConfiguration(){// Gets or sets a value indicating the prefix of generated column names.EmptyColumnNamePrefix="Column",// Gets or sets a value indicating whether to use a row from the // data as column names.UseHeaderRow=true,// Gets or sets a callback to determine which row is the header row. // Only called when UseHeaderRow = true.ReadHeaderRow=(rowReader)=>{// F.ex skip the first row and use the 2nd row as column headers://rowReader.Read();},// Gets or sets a callback to determine whether to include the // current row in the DataTable.FilterRow=(rowReader)=>{returntrue;},// Gets or sets a callback to determine whether to include the specific// column in the DataTable. Called once per column after reading the // headers.FilterColumn=(rowReader, columnIndex)=>{returntrue;}}});return result;}catch(Exception ex){returnnull;}finally{
stream.Close();
stream.Dispose();}}
Es ist 2020 und dies ist eine großartige Lösung im Vergleich zu einigen der älteren Antworten hier. Es ist schön verpackt und verwendet eine beliebte und leichte Bibliothek von NuGet. Und es ist flexibel - wenn sich Ihre CSV im Speicher befindet, übergeben Sie sie einfach als MemoryStreamDateipfad. Die von OP result.Tables[0]
angeforderte Datentabelle kann
1
Wenn ich nur diese Erweiterungsmethoden teile, hoffe ich, dass sie jemandem helfen können.
publicstaticList<string>ToCSV(thisDataSet ds,char separator ='|'){List<string> lResult =newList<string>();foreach(DataTable dt in ds.Tables){StringBuilder sb =newStringBuilder();IEnumerable<string> columnNames = dt.Columns.Cast<DataColumn>().Select(column => column.ColumnName);
sb.AppendLine(string.Join(separator.ToString(), columnNames));foreach(DataRow row in dt.Rows){IEnumerable<string> fields = row.ItemArray.Select(field =>string.Concat("\"", field.ToString().Replace("\"","\"\""),"\""));
sb.AppendLine(string.Join(separator.ToString(), fields));}
lResult.Add(sb.ToString());}return lResult;}publicstaticDataSetCSVtoDataSet(thisList<string> collectionCSV,char separator ='|'){var ds =newDataSet();foreach(var csv in collectionCSV){var dt =newDataTable();var readHeader =false;foreach(var line in csv.Split(new[]{Environment.NewLine},StringSplitOptions.None)){if(!readHeader){foreach(var c in line.Split(separator))
dt.Columns.Add(c);}else{
dt.Rows.Add(line.Split(separator));}}
ds.Tables.Add(dt);}return ds;}
Die Verwendung dieser Bibliothek zum Laden von a DataTableist äußerst einfach.
using var tr =File.OpenText("data.csv");
using var dr =CsvDataReader.Create(tr);var dt =newDataTable();
dt.Load(dr);
Angenommen, Ihre Datei ist eine durch Kommas getrennte Standarddatei mit Überschriften, das ist alles, was Sie brauchen. Es gibt auch Optionen zum Lesen von Dateien ohne Header und zum Verwenden alternativer Trennzeichen usw.
Es ist auch möglich, ein benutzerdefiniertes Schema für die CSV-Datei bereitzustellen, damit Spalten als etwas anderes als stringWerte behandelt werden können. Auf diese Weise können die DataTableSpalten mit Werten geladen werden, mit denen einfacher gearbeitet werden kann, da Sie sie beim Zugriff nicht erzwingen müssen.
var schema =newTypedCsvSchema();
schema.Add(0,typeof(int));
schema.Add(1,typeof(string));
schema.Add(2,typeof(double?));
schema.Add(3,typeof(DateTime));
schema.Add(4,typeof(DateTime?));var options =newCsvDataReaderOptions{Schema= schema
};
using var tr =GetData();
using var dr =CsvDataReader.Create(tr, options);
TypedCsvSchemaist eine Implementierung, ICsvSchemaProviderdie eine einfache Möglichkeit bietet, die Arten der Spalten zu definieren. Es ist jedoch auch möglich, eine benutzerdefinierte Funktion bereitzustellen, ICsvSchemaProviderwenn Sie mehr Metadaten bereitstellen möchten, z. B. Eindeutigkeit oder eingeschränkte Spaltengröße usw.
Antworten:
Hier ist eine hervorragende Klasse, die CSV-Daten mithilfe der Datenstruktur zum Erstellen der Datentabelle in eine Datentabelle kopiert:
Ein tragbarer und effizienter generischer Parser für Flatfiles
Es ist einfach zu konfigurieren und einfach zu bedienen. Ich fordere Sie auf, einen Blick darauf zu werfen.
quelle
Ich habe
OleDb
Anbieter verwendet. Es gibt jedoch Probleme, wenn Sie Zeilen mit numerischen Werten lesen, diese jedoch als Text behandeln möchten. Sie können dieses Problem jedoch umgehen, indem Sie eineschema.ini
Datei erstellen. Hier ist meine Methode, die ich verwendet habe:quelle
Ich habe mich entschieden zu verwenden Sebastien Lorions Csv Reader entschieden .
Jay Riggs Vorschlag ist auch eine großartige Lösung, aber ich brauchte einfach nicht alle Funktionen, die das bietet Andrew Rissings Generic Parser bietet.
UPDATE 25.10.2010
Nach dem Gebrauch ich fast anderthalb Jahre lang den CSV-Reader Sebastien Lorion in meinem Projekt verwendet habe, habe ich festgestellt, dass er beim Parsen einiger CSV-Dateien, von denen ich glaube, dass sie gut geformt sind, Ausnahmen auslöst.
Also habe ich zu Andrew Rissings Generic Parser gewechselt und es scheint viel besser zu laufen.
UPDATE 22.09.2014
Heutzutage verwende ich meistens diese Erweiterungsmethode, um abgegrenzten Text zu lesen:
https://github.com/Core-Techs/Common/blob/master/CoreTechs.Common/Text/DelimitedTextExtensions.cs#L22
https://www.nuget.org/packages/CoreTechs.Common/
UPDATE 20.02.2015
Beispiel:
quelle
Hey, es funktioniert zu 100%
CSV-Bild
Datentabelle Importiert
quelle
Wir haben immer den Jet.OLEDB-Treiber verwendet, bis wir zu 64-Bit-Anwendungen gingen. Microsoft hat und wird keinen 64-Bit-Jet-Treiber veröffentlichen. Hier ist eine einfache Lösung, die File.ReadAllLines und String.Split verwendet, um die CSV-Datei zu lesen und zu analysieren und eine DataTable manuell zu laden. Wie oben erwähnt, wird die Situation, in der einer der Spaltenwerte ein Komma enthält, NICHT behandelt. Wir verwenden dies hauptsächlich zum Lesen benutzerdefinierter Konfigurationsdateien. Das Schöne an der Verwendung von CSV-Dateien ist, dass wir sie in Excel bearbeiten können.
quelle
Dies ist der Code, den ich benutze, aber Ihre Apps müssen mit Net Version 3.5 ausgeführt werden
quelle
Sie können dies erreichen, indem Sie die DLL Microsoft.VisualBasic.FileIO.TextFieldParser in C # verwenden
quelle
quelle
Ich bin auf diesen Code gestoßen, der Linq und Regex verwendet, um eine CSV-Datei zu analysieren. Der Artikel, auf den verwiesen wird, ist jetzt über anderthalb Jahre alt, hat jedoch keine bessere Möglichkeit gefunden, eine CSV mit Linq (und Regex) zu analysieren. Die Einschränkung ist, dass der hier angewendete reguläre Ausdruck für durch Kommas getrennte Dateien gilt (erkennt Kommas in Anführungszeichen!) Und dass es für Header möglicherweise nicht gut ist, aber es gibt eine Möglichkeit, diese zu überwinden). Nehmen Sie einen Höhepunkt:
quelle
Die beste Option, die ich gefunden habe und die Probleme behebt, bei denen möglicherweise verschiedene Versionen von Office installiert sind, sowie 32/64-Bit-Probleme, wie sie von Chuck Bevitt erwähnt wurden , sind FileHelpers .
Es kann mit NuGet zu Ihren Projektreferenzen hinzugefügt werden und bietet eine einzeilige Lösung:
quelle
Für diejenigen unter Ihnen, die keine externe Bibliothek verwenden möchten und OleDB nicht verwenden möchten, siehe das folgende Beispiel. Alles, was ich gefunden habe, war entweder OleDB, eine externe Bibliothek oder einfach das Aufteilen anhand eines Kommas! Für meinen Fall funktionierte OleDB nicht, also wollte ich etwas anderes.
Ich habe einen Artikel von MarkJ gefunden, der auf die hier gezeigte Microsoft.VisualBasic.FileIO.TextFieldParser-Methode verweist . Der Artikel ist in VB geschrieben und gibt keine Datentabelle zurück. Siehe mein Beispiel unten.
quelle
Sehr einfache Antwort: Wenn Sie keine komplexe CSV-Datei haben, die eine einfache Split-Funktion verwenden kann, funktioniert dies gut für den Import (beachten Sie, dass dies als Zeichenfolgen importiert wird, ich mache Datentypkonvertierungen später, wenn ich muss).
Meine Methode, wenn ich eine Tabelle mit einem String [] -Trennzeichen importiere und das Problem behandle, bei dem die aktuelle Zeile, die ich lese, möglicherweise zur nächsten Zeile in der CSV- oder Textdatei <- gegangen ist. In diesem Fall möchte ich eine Schleife ausführen, bis ich sie erhalte auf die Gesamtzahl der Zeilen in der ersten Zeile (Spalten)
quelle
Geändert von Herrn ChuckBevitt
Arbeitslösung:
quelle
Hier ist eine Lösung, die den ODBC-Texttreiber von ADO.Net verwendet:
Nach dem Ausfüllen können Sie Eigenschaften der Datentabelle wie ColumnName bewerten, um alle Funktionen der ADO.Net-Datenobjekte zu nutzen.
In VS2008 können Sie Linq verwenden, um den gleichen Effekt zu erzielen.
HINWEIS: Dies kann ein Duplikat dieser SO-Frage sein.
quelle
Ich kann nicht widerstehen, meinen eigenen Dreh hinzuzufügen. Das ist so viel besser und kompakter als das, was ich in der Vergangenheit verwendet habe.
Diese Lösung:
Folgendes habe ich mir ausgedacht:
Es hängt von einer Erweiterungsmethode (
Unique
) ab, doppelte Spaltennamen zu verarbeiten, die als meine Antwort in gefunden werden unter Anhängen eindeutiger Zahlen an eine Liste von Zeichenfolgen zu finden sindUnd hier ist die
BlankToNothing
Hilfsfunktion:quelle
Mit Cinchoo ETL - einer Open Source-Bibliothek - können Sie CSV-Dateien mit wenigen Codezeilen problemlos in DataTable konvertieren.
Weitere Informationen finden Sie im Artikel zum Codeprojekt .
Ich hoffe es hilft.
quelle
Verwenden von: https://joshclose.github.io/CsvHelper/
quelle
Configuration
umbenannt wurdeCsvConfiguration
, um Namespace-Konflikte zu vermeiden. Demo dieser Antwort funktioniert: dotnetfiddle.net/sdwc6iIch benutze eine Bibliothek namens ExcelDataReader, die Sie auf NuGet finden können. Stellen Sie sicher, dass Sie sowohl ExcelDataReader als auch die Erweiterung ExcelDataReader.DataSet installieren (letztere bietet die erforderliche AsDataSet-Methode, auf die unten verwiesen wird).
Ich habe alles in einer Funktion zusammengefasst, Sie können es direkt in Ihren Code kopieren. Geben Sie einen Pfad zur CSV-Datei ein. Sie erhalten einen Datensatz mit einer Tabelle.
quelle
MemoryStream
Dateipfad. Die von OPresult.Tables[0]
Wenn ich nur diese Erweiterungsmethoden teile, hoffe ich, dass sie jemandem helfen können.
quelle
Verwenden Sie diese Funktion, um alle Probleme mit Komma und Anführungszeichen zu lösen:
quelle
quelle
Ich habe kürzlich einen CSV-Parser für .NET geschrieben, von dem ich behaupte, dass er derzeit der schnellste ist , der als Nuget-Paket verfügbar ist: Sylvan.Data.Csv .
Die Verwendung dieser Bibliothek zum Laden von a
DataTable
ist äußerst einfach.Angenommen, Ihre Datei ist eine durch Kommas getrennte Standarddatei mit Überschriften, das ist alles, was Sie brauchen. Es gibt auch Optionen zum Lesen von Dateien ohne Header und zum Verwenden alternativer Trennzeichen usw.
Es ist auch möglich, ein benutzerdefiniertes Schema für die CSV-Datei bereitzustellen, damit Spalten als etwas anderes als
string
Werte behandelt werden können. Auf diese Weise können dieDataTable
Spalten mit Werten geladen werden, mit denen einfacher gearbeitet werden kann, da Sie sie beim Zugriff nicht erzwingen müssen.TypedCsvSchema
ist eine Implementierung,ICsvSchemaProvider
die eine einfache Möglichkeit bietet, die Arten der Spalten zu definieren. Es ist jedoch auch möglich, eine benutzerdefinierte Funktion bereitzustellen,ICsvSchemaProvider
wenn Sie mehr Metadaten bereitstellen möchten, z. B. Eindeutigkeit oder eingeschränkte Spaltengröße usw.quelle