Rzeczywiście doskonałe. U mnie zadziałało idealnie po wyjęciu z pudełka, nawet bez czytania dokumentacji.
smirkingman
Czy to zadziała w przypadku plików CSV, w których każdy wiersz może mieć inną strukturę? Mam plik dziennika z różnymi typami zarejestrowanych zdarzeń, które musiałyby zostać rozdzielone na wiele tabel.
gonzobrains
2
@gonzobrains - prawdopodobnie nie; podstawowym założeniem pliku CSV jest prostokątna struktura danych oparta na jednym zestawie nagłówków kolumn określonych w pierwszym wierszu. To, co masz, wydaje się być bardziej ogólnymi, oddzielonymi przecinkami danymi, wymagającymi bardziej wyrafinowanego „ETL” do przeanalizowania z pliku na instancje obiektów różnych typów (które mogą obejmować DataRows różnych DataTables).
KeithS
93
Korzystam z OleDbdostawcy. Jednak występują problemy, jeśli czytasz w wierszach, które mają wartości liczbowe, ale chcesz, aby były traktowane jako tekst. Możesz jednak obejść ten problem, tworząc schema.iniplik. Oto moja metoda, której użyłem:
// 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;}}
Dzięki stary. To mi pomogło. Miałem plik CSV, w którym przecinki były nie tylko separatorami, ale znajdowały się wszędzie w wartościach wielu kolumn, więc wymyślenie wyrażenia regularnego, które podzieliłoby linię, było dość trudne. OleDbProvider poprawnie wywnioskował schemat.
Galilyou,
Implementacja ma sens, ale jak radzimy sobie z komórkami zawierającymi mieszane typy danych. Na przykład 40C itp.?
GKED
GKED, jeśli dane, które czytasz, zawsze mają oczekiwany zestaw kolumn i typów, możesz umieścić w tym samym folderze plik shema.ini, który przekazuje dostawcy OleDb informacje o kolumnach. Oto łącze do artykułu firmy Microsoft, który zawiera szczegółowe informacje na temat struktury pliku. msdn.microsoft.com/en-us/library/…
Jim Scott
4
Chociaż ta odpowiedź zadziała, zdecydowanie odradzam. Wprowadzasz zależność zewnętrzną, która może kolidować z innymi instalacjami pakietu Office na tym samym komputerze (używać programu Excel w lokalnym środowisku deweloperskim?), W zależności od zainstalowanych wersji. Istnieją pakiety NuGet (ExcelDataReader, CsvHelper), które robią to w bardziej wydajny i przenośny sposób.
A. Murray,
1
@ A.Murray - Co dokładnie masz na myśli? Używa wbudowanego dostawcy OleDb w System.Data.dll. Nie musisz instalować żadnych dodatkowych „sterowników”. Byłbym zszokowany w dzisiejszych czasach, gdyby jakakolwiek instalacja systemu Windows nie miała zainstalowanego podstawowego sterownika Jet. To jest CSV z lat 90-tych ...
Sugestia Jaya Riggsa jest również świetnym rozwiązaniem, ale po prostu nie potrzebowałem wszystkich funkcji, które zapewnia Generic Parser Andrew Rissinga .
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());}
Zgadzam się, że czytnik CSV Sebastiena Loriena jest świetny. Używam go do ciężkiego przetwarzania CSV, ale używam również Rissingów Andrew's do małych zadań i dobrze mi to służyło. Baw się dobrze!
Jay Riggs
Jak mogę użyć tych klas, aby załadować CSV do DATATABLE?
Muflix,
Próbowałem tego, ale kolekcja it.Current.Keys zwraca „System.Linq.Enumerable + WhereSelectListIterator`2 [System.Int32, System.Char]” zamiast nazwy kolumny. Jakieś przemyślenia, dlaczego?
user3658298
Czy możesz używać ograniczników wieloznakowych?
rolki
Nie, ale myślałem o umożliwieniu tego.
Ronnie Overby
32
Hej, działa w 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 Otrzymuję błąd w ostatnim wierszu, czy tam jesteś, a następnie podaj inne dane kontaktowe
Sunil Acharya
Chociaż nie korzystałem dokładnie z tej wersji, to na jej podstawie rozwiązałem swój problem. Dziękuję Ci. Działa bardzo dobrze.
nrod
13
Zawsze używaliśmy sterownika Jet.OLEDB, dopóki nie zaczęliśmy korzystać z aplikacji 64-bitowych. Firma Microsoft nie wydała i nie wyda 64-bitowego sterownika Jet. Oto proste rozwiązanie, które wymyśliliśmy, które wykorzystuje File.ReadAllLines i String.Split do odczytywania i analizowania pliku CSV oraz ręcznego ładowania DataTable. Jak wspomniano powyżej, NIE obsługuje sytuacji, w których jedna z wartości kolumny zawiera przecinek. Używamy tego głównie do czytania niestandardowych plików konfiguracyjnych - fajną częścią korzystania z plików CSV jest to, że możemy je edytować w programie Excel.
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);}
to jest kod, którego używam, ale Twoje aplikacje muszą działać w sieci 3.5
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();}
Natknąłem się na ten fragment kodu, który używa Linq i regex do analizowania pliku CSV. Artykuł odsyłający ma już ponad półtora roku, ale nie znalazłem lepszego sposobu analizowania pliku CSV przy użyciu Linq (i wyrażenia regularnego) niż ten. Zastrzeżenie polega na tym, że zastosowane tutaj wyrażenie regularne odnosi się do plików rozdzielanych przecinkami (wykryje przecinki w cudzysłowach!) I może nie pasować dobrze do nagłówków, ale istnieje sposób, aby to obejść). Weź szczyt:
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
Najlepszą opcją, jaką znalazłem, i rozwiązuje problemy, w których możesz mieć zainstalowane różne wersje pakietu Office, a także problemy 32/64-bitowe, o których wspomniał Chuck Bevitt , to FileHelpers .
Można go dodać do odwołań do projektu przy użyciu narzędzia NuGet i zapewnia rozwiązanie jednowierszowe:
czy możesz powiedzieć, co to jest CommonEngine? NuGet jest taki sam jak NuGet.Core. Znalazłem tylko NuGet.Core w referencjach
sindhu jampani
To FileHelpers, którego potrzebujesz. Jeśli masz pakiet NuGet, dodaj go za pomocą NuGet. W przeciwnym razie po prostu dodaj go jako zespół do projektu. CommonEngine jest częścią FileHelpers.
Neo
3
Dla tych, którzy nie chcą używać zewnętrznej biblioteki i wolą nie używać OleDB, zobacz poniższy przykład. Wszystko, co znalazłem, to OleDB, zewnętrzna biblioteka lub po prostu podzielone na podstawie przecinka! W moim przypadku OleDB nie działał, więc chciałem czegoś innego.
Znalazłem artykuł MarkJ, który odwoływał się do metody Microsoft.VisualBasic.FileIO.TextFieldParser, jak widać tutaj . Artykuł jest napisany w VB i nie zwraca datatable, więc zobacz mój przykład poniżej.
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;}
Bardzo podstawowa odpowiedź: jeśli nie masz złożonego pliku csv, który może używać prostej funkcji podziału, będzie to dobrze działać przy importowaniu (zwróć uwagę, że importuje to jako ciągi, wykonuję później konwersje typów danych, jeśli zajdzie taka potrzeba)
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;}
Moja metoda, jeśli importuję tabelę z separatorem ciągów [] i rozwiązuje problem, w którym bieżący wiersz, który czytam, mógł przejść do następnego wiersza w pliku csv lub tekstowym <- W takim przypadku chcę zapętlić, dopóki nie otrzymam do całkowitej liczby wierszy w pierwszym wierszu (kolumnach)
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;}
Świetnie, po prostu jeszcze nie zadeklarowałeś wierszy jako string [].
Styl zwierzęcy
@AnimalStyle masz rację - zaktualizowano za pomocą bardziej niezawodnej metody i zadeklarowanych wierszy
Matt Farguson
3
Zmodyfikowano z Mr ChuckaBevitta
Rozwiązanie robocze:
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);}
Więc to rozwiązuje problem z pamięcią, prawda? To jest przetwarzanie wiersz po wierszu i nie utrzymuje się w pamięci, więc nie powinno być żadnych wyjątków? Podoba mi się sposób, w jaki jest to przetwarzane, ale czy File.ReadAllLines () nie zapisuje wszystkiego w pamięci? Myślę, że powinieneś użyć File.ReadLines (), aby uniknąć ogromnego bufora pamięci? To dobra odpowiedź na zadane pytanie, które chcę tylko wiedzieć o problemach z pamięcią.
DtechNet
2
Oto rozwiązanie wykorzystujące sterownik tekstowy ODBC ADO.Net:
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
Po wypełnieniu można wycenić właściwości datatable, takie jak ColumnName, aby wykorzystać wszystkie możliwości obiektów danych ADO.Net.
W VS2008 możesz użyć Linq, aby osiągnąć ten sam efekt.
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;}
Zauważ, że w wersji 13Configuration nazwa została zmieniona na, CsvConfigurationaby uniknąć konfliktów przestrzeni nazw. Demo tej odpowiedzi działa: dotnetfiddle.net/sdwc6i
dbc
2
Używam biblioteki o nazwie ExcelDataReader, którą można znaleźć w NuGet. Pamiętaj, aby zainstalować zarówno rozszerzenie ExcelDataReader, jak i rozszerzenie ExcelDataReader.DataSet (to drugie zapewnia wymaganą metodę AsDataSet, o której mowa poniżej).
Wszystko zawarłem w jednej funkcji, możesz ją skopiować bezpośrednio w swoim kodzie. Podaj ścieżkę do pliku CSV, a otrzymasz zestaw danych z jedną tabelą.
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();}}
Jest rok 2020 i jest to świetne rozwiązanie w porównaniu do niektórych starszych odpowiedzi tutaj. Jest ładnie zapakowany i używa popularnej i lekkiej biblioteki z NuGet. I jest elastyczny - jeśli twój MemoryStreamplik CSV jest w pamięci, po prostu przekaż go jako ścieżkę pliku zamiast. DataTable, o którą prosił OP, można łatwo wyodrębnić z DataSet w następujący sposób:result.Tables[0]
Tawab Wakil
1
Po prostu udostępniając te metody rozszerzenia, mam nadzieję, że może to komuś pomóc.
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;}
Używanie tej biblioteki do załadowania pliku DataTablejest niezwykle łatwe.
using var tr =File.OpenText("data.csv");
using var dr =CsvDataReader.Create(tr);var dt =newDataTable();
dt.Load(dr);
Zakładając, że twój plik to standardowe pliki oddzielone przecinkami z nagłówkami, to wszystko, czego potrzebujesz. Istnieją również opcje umożliwiające odczytywanie plików bez nagłówków i używanie alternatywnych ograniczników itp.
Możliwe jest również zapewnienie niestandardowego schematu dla pliku CSV, aby kolumny mogły być traktowane jako coś innego niż stringwartości. Umożliwi to DataTablezaładowanie kolumn wartościami, z którymi będzie łatwiej pracować, ponieważ nie będziesz musiał ich wymuszać, gdy uzyskasz do nich dostęp.
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);
TypedCsvSchemato implementacja, ICsvSchemaProviderktóra zapewnia prosty sposób definiowania typów kolumn. Możliwe jest jednak również podanie niestandardowego, ICsvSchemaProvidergdy chcesz podać więcej metadanych, takich jak unikalność lub ograniczony rozmiar kolumny itp.
Odpowiedzi:
Oto doskonała klasa, która skopiuje dane CSV do datatable przy użyciu struktury danych do utworzenia DataTable:
Przenośny i wydajny ogólny parser dla plików płaskich
Jest łatwy w konfiguracji i obsłudze. Zachęcam do obejrzenia.
źródło
Korzystam z
OleDb
dostawcy. Jednak występują problemy, jeśli czytasz w wierszach, które mają wartości liczbowe, ale chcesz, aby były traktowane jako tekst. Możesz jednak obejść ten problem, tworzącschema.ini
plik. Oto moja metoda, której użyłem:źródło
Zdecydowałem się użyć czytnika CSV Sebastiena Loriona .
Sugestia Jaya Riggsa jest również świetnym rozwiązaniem, ale po prostu nie potrzebowałem wszystkich funkcji, które zapewnia Generic Parser Andrew Rissinga .
AKTUALIZACJA 25.10.2010
Po prawie półtorarocznym używaniu czytnika Csv Sebastiena Loriona w moim projekcie odkryłem, że rzuca on wyjątki podczas analizowania niektórych plików csv, które uważam za dobrze uformowane.
Więc przeszedłem na Generic Parser Andrew Rissinga i wydaje się, że działa znacznie lepiej.
AKTUALIZACJA 22.09.2014
Obecnie używam głównie tej metody rozszerzenia do czytania tekstu rozdzielanego:
https://github.com/Core-Techs/Common/blob/master/CoreTechs.Common/Text/DelimitedTextExtensions.cs#L22
https://www.nuget.org/packages/CoreTechs.Common/
AKTUALIZACJA 20.02.2015
Przykład:
źródło
Hej, działa w 100%
Obraz CSV
Tabela danych zaimportowana
źródło
Zawsze używaliśmy sterownika Jet.OLEDB, dopóki nie zaczęliśmy korzystać z aplikacji 64-bitowych. Firma Microsoft nie wydała i nie wyda 64-bitowego sterownika Jet. Oto proste rozwiązanie, które wymyśliliśmy, które wykorzystuje File.ReadAllLines i String.Split do odczytywania i analizowania pliku CSV oraz ręcznego ładowania DataTable. Jak wspomniano powyżej, NIE obsługuje sytuacji, w których jedna z wartości kolumny zawiera przecinek. Używamy tego głównie do czytania niestandardowych plików konfiguracyjnych - fajną częścią korzystania z plików CSV jest to, że możemy je edytować w programie Excel.
źródło
to jest kod, którego używam, ale Twoje aplikacje muszą działać w sieci 3.5
źródło
Możesz to osiągnąć za pomocą Microsoft.VisualBasic.FileIO.TextFieldParser dll w C #
źródło
źródło
Natknąłem się na ten fragment kodu, który używa Linq i regex do analizowania pliku CSV. Artykuł odsyłający ma już ponad półtora roku, ale nie znalazłem lepszego sposobu analizowania pliku CSV przy użyciu Linq (i wyrażenia regularnego) niż ten. Zastrzeżenie polega na tym, że zastosowane tutaj wyrażenie regularne odnosi się do plików rozdzielanych przecinkami (wykryje przecinki w cudzysłowach!) I może nie pasować dobrze do nagłówków, ale istnieje sposób, aby to obejść). Weź szczyt:
źródło
Najlepszą opcją, jaką znalazłem, i rozwiązuje problemy, w których możesz mieć zainstalowane różne wersje pakietu Office, a także problemy 32/64-bitowe, o których wspomniał Chuck Bevitt , to FileHelpers .
Można go dodać do odwołań do projektu przy użyciu narzędzia NuGet i zapewnia rozwiązanie jednowierszowe:
źródło
Dla tych, którzy nie chcą używać zewnętrznej biblioteki i wolą nie używać OleDB, zobacz poniższy przykład. Wszystko, co znalazłem, to OleDB, zewnętrzna biblioteka lub po prostu podzielone na podstawie przecinka! W moim przypadku OleDB nie działał, więc chciałem czegoś innego.
Znalazłem artykuł MarkJ, który odwoływał się do metody Microsoft.VisualBasic.FileIO.TextFieldParser, jak widać tutaj . Artykuł jest napisany w VB i nie zwraca datatable, więc zobacz mój przykład poniżej.
źródło
Bardzo podstawowa odpowiedź: jeśli nie masz złożonego pliku csv, który może używać prostej funkcji podziału, będzie to dobrze działać przy importowaniu (zwróć uwagę, że importuje to jako ciągi, wykonuję później konwersje typów danych, jeśli zajdzie taka potrzeba)
Moja metoda, jeśli importuję tabelę z separatorem ciągów [] i rozwiązuje problem, w którym bieżący wiersz, który czytam, mógł przejść do następnego wiersza w pliku csv lub tekstowym <- W takim przypadku chcę zapętlić, dopóki nie otrzymam do całkowitej liczby wierszy w pierwszym wierszu (kolumnach)
źródło
Zmodyfikowano z Mr ChuckaBevitta
Rozwiązanie robocze:
źródło
Oto rozwiązanie wykorzystujące sterownik tekstowy ODBC ADO.Net:
Po wypełnieniu można wycenić właściwości datatable, takie jak ColumnName, aby wykorzystać wszystkie możliwości obiektów danych ADO.Net.
W VS2008 możesz użyć Linq, aby osiągnąć ten sam efekt.
UWAGA: To może być duplikatem tego pytania SO.
źródło
Nie mogę się oprzeć dodaniu do tego własnego spinu. To jest o wiele lepsze i bardziej kompaktowe niż to, czego używałem w przeszłości.
To rozwiązanie:
Oto, co wymyśliłem:
Zależy to od metody rozszerzenia (
Unique
), która obsługuje zduplikowane nazwy kolumn, które mają być znalezione jako moja odpowiedź w Jak dołączyć unikalne liczby do listy ciągówA oto
BlankToNothing
funkcja pomocnicza:źródło
Dzięki Cinchoo ETL - bibliotece open source, możesz łatwo przekonwertować plik CSV do DataTable za pomocą kilku wierszy kodu.
Aby uzyskać więcej informacji, odwiedź codeproject artykule .
Mam nadzieję, że to pomoże.
źródło
używając: https://joshclose.github.io/CsvHelper/
źródło
Configuration
nazwa została zmieniona na,CsvConfiguration
aby uniknąć konfliktów przestrzeni nazw. Demo tej odpowiedzi działa: dotnetfiddle.net/sdwc6iUżywam biblioteki o nazwie ExcelDataReader, którą można znaleźć w NuGet. Pamiętaj, aby zainstalować zarówno rozszerzenie ExcelDataReader, jak i rozszerzenie ExcelDataReader.DataSet (to drugie zapewnia wymaganą metodę AsDataSet, o której mowa poniżej).
Wszystko zawarłem w jednej funkcji, możesz ją skopiować bezpośrednio w swoim kodzie. Podaj ścieżkę do pliku CSV, a otrzymasz zestaw danych z jedną tabelą.
źródło
MemoryStream
plik CSV jest w pamięci, po prostu przekaż go jako ścieżkę pliku zamiast. DataTable, o którą prosił OP, można łatwo wyodrębnić z DataSet w następujący sposób:result.Tables[0]
Po prostu udostępniając te metody rozszerzenia, mam nadzieję, że może to komuś pomóc.
źródło
Użyj tego, jedna funkcja rozwiązuje wszystkie problemy z przecinkami i cudzysłowami:
źródło
źródło
Niedawno napisałem parser CSV dla .NET, który, jak twierdzę, jest obecnie najszybszym dostępnym pakietem nuget : Sylvan.Data.Csv .
Używanie tej biblioteki do załadowania pliku
DataTable
jest niezwykle łatwe.Zakładając, że twój plik to standardowe pliki oddzielone przecinkami z nagłówkami, to wszystko, czego potrzebujesz. Istnieją również opcje umożliwiające odczytywanie plików bez nagłówków i używanie alternatywnych ograniczników itp.
Możliwe jest również zapewnienie niestandardowego schematu dla pliku CSV, aby kolumny mogły być traktowane jako coś innego niż
string
wartości. Umożliwi toDataTable
załadowanie kolumn wartościami, z którymi będzie łatwiej pracować, ponieważ nie będziesz musiał ich wymuszać, gdy uzyskasz do nich dostęp.TypedCsvSchema
to implementacja,ICsvSchemaProvider
która zapewnia prosty sposób definiowania typów kolumn. Możliwe jest jednak również podanie niestandardowego,ICsvSchemaProvider
gdy chcesz podać więcej metadanych, takich jak unikalność lub ograniczony rozmiar kolumny itp.źródło