Excelente de hecho. Funcionó perfectamente para mí fuera de la caja, sin siquiera leer la documentación.
smirkingman
¿Funcionará esto en archivos CSV donde cada fila puede ser de una estructura diferente? Tengo un archivo de registro con diferentes tipos de eventos registrados que deberían separarse en varias tablas.
gonzobrains
2
@gonzobrains - Probablemente no; La suposición básica de un archivo CSV es una estructura de datos rectangular basada en un único conjunto de encabezados de columna especificados en la primera línea. Lo que tiene parece ser datos discriminados, delimitados por comas, más genéricos, que requieren "ETL" más sofisticados para analizar desde el archivo a instancias de objetos de diversos tipos (que podrían incluir filas de datos de diferentes tablas de datos).
KeithS
93
He estado usando el OleDbproveedor. Sin embargo, tiene problemas si está leyendo en filas que tienen valores numéricos pero desea que se traten como texto. Sin embargo, puede solucionar ese problema creando un schema.iniarchivo. Aquí está mi método que utilicé:
// 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;}}
Gracias amigo. Eso me ayudó. Tenía un archivo CSV en el que las comas no solo eran separadores, estaban en todas partes dentro de muchos valores de columnas, por lo que crear una expresión regular que dividiría la línea fue un poco desafiante. OleDbProvider dedujo el esquema correctamente.
Galilyou
La implementación tiene sentido, pero ¿cómo manejamos las celdas que contienen tipos de datos mixtos? Por ejemplo, 40C y etc.
GKED
GKED, si los datos que está leyendo siempre tienen un conjunto esperado de columnas y tipos, puede colocar en la misma carpeta un archivo shema.ini que le brinde información sobre las columnas a los proveedores de OleDb. Aquí hay un enlace a un artículo de Microsoft que proporciona detalles sobre cómo estructurar el archivo. msdn.microsoft.com/en-us/library/…
Jim Scott
44
Si bien esta respuesta funcionará, recomendaría encarecidamente que no lo haga. Introduce una dependencia externa que puede entrar en conflicto con otras instalaciones de oficina en la misma máquina (¿usar Excel en su entorno de desarrollo local?), Dependiendo de las versiones instaladas. Existen paquetes NuGet (ExcelDataReader, CsvHelper) que hacen esto de manera más eficiente y portátil.
A. Murray el
1
@ A.Murray - ¿Qué quieres decir exactamente? Esto utiliza el proveedor OleDb integrado en System.Data.dll. No necesita instalar ningún "controlador" adicional. Y me sorprendería hoy en día si alguna instalación de Windows no tuviera instalado el controlador Jet básico. Este es el CSV de 1990 ...
La sugerencia de Jay Riggs también es una gran solución, pero no necesitaba todas las características que proporciona el analizador genérico de Andrew Rissing .
ACTUALIZACIÓN 25/10/2010
Después de usar el Lector de Csv de Sebastien Lorion en mi proyecto durante casi un año y medio, descubrí que arroja excepciones al analizar algunos archivos csv que creo que están bien formados.
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());}
Estoy de acuerdo en que el lector CSV de Sebastien Lorien es genial. Lo uso para el procesamiento pesado de CSV, pero también he usado Andrew's Rissing para pequeños trabajos y me ha servido bien. ¡Que te diviertas!
Jay Riggs
¿Cómo puedo usar estas clases para cargar CSV en DATATABLE?
Muflix
Intenté esto, pero la colección it.Current.Keys regresa con "System.Linq.Enumerable + WhereSelectListIterator`2 [System.Int32, System.Char]" en lugar del nombre de la columna. ¿Alguna idea de por qué?
user3658298
¿Puedes usar delimitadores de caracteres múltiples?
lanza el
No, pero pensé en habilitar eso.
Ronnie Overby el
32
Hola, está funcionando al 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 Recibo el error en la última fila, ¿estás ahí y luego te doy otra información de contacto
Sunil Acharya
Aunque no utilicé esta versión exactamente, se basó en que resolví mi problema. Gracias. Funciona muy bien
nrod el
13
Siempre solíamos usar el controlador Jet.OLEDB, hasta que comenzamos a utilizar aplicaciones de 64 bits. Microsoft no ha lanzado ni lanzará un controlador Jet de 64 bits. Aquí hay una solución simple que se nos ocurrió que usa File.ReadAllLines y String.Split para leer y analizar el archivo CSV y cargar manualmente una DataTable. Como se señaló anteriormente, NO maneja la situación en la que uno de los valores de la columna contiene una coma. Usamos esto principalmente para leer archivos de configuración personalizados; lo bueno de usar archivos CSV es que podemos editarlos en 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);}
este es el código que uso, pero sus aplicaciones deben ejecutarse con la versión neta 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();}
Me encontré con este código que usa Linq y regex para analizar un archivo CSV. El artículo de referencia ahora tiene más de un año y medio, pero no ha encontrado una forma más ordenada de analizar un CSV usando Linq (y regex) que esto. La advertencia es que la expresión regular aplicada aquí es para archivos delimitados por comas (¡detectará comas dentro de comillas!) Y que puede que no se adapte bien a los encabezados, pero hay una manera de superarlos). Toma un pico:
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
FileHelpers es la mejor opción que he encontrado, y resuelve problemas en los que puede tener instaladas diferentes versiones de Office, y también problemas de 32/64 bits como Chuck Bevitt .
Se puede agregar a las referencias de su proyecto usando NuGet y proporciona una solución de una sola línea:
¿Puedes decir qué es CommonEngine? NuGet es lo mismo que NuGet.Core. Encontré solo NuGet. Core en las referencias
sindhu jampani
Es FileHelpers lo que necesitas. Si tiene NuGet, agréguelo con NuGet. De lo contrario, simplemente agréguelo como un ensamblaje en su proyecto. CommonEngine es parte de FileHelpers.
Neo
3
Para aquellos de ustedes que no desean usar una biblioteca externa y prefieren no usar OleDB, consulte el siguiente ejemplo. ¡Todo lo que encontré fue OleDB, una biblioteca externa, o simplemente dividir en base a una coma! Para mi caso, OleDB no funcionaba, así que quería algo diferente.
Encontré un artículo de MarkJ que hacía referencia al método Microsoft.VisualBasic.FileIO.TextFieldParser como se ve aquí . El artículo está escrito en VB y no devuelve una tabla de datos, así que vea mi ejemplo a continuación.
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;}
Respuesta muy básica: si no tiene un csv complejo que pueda usar una función de división simple, esto funcionará bien para importar (tenga en cuenta que esto importa como cadenas, luego haré conversiones de tipo de datos si es necesario)
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;}
Mi método si estoy importando una tabla con un separador de cadena [] y maneja el problema donde la línea actual que estoy leyendo puede haber ido a la siguiente línea en el archivo csv o de texto <- EN cuyo caso quiero hacer un bucle hasta que llegue al número total de líneas en la primera fila (columnas)
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;}
Es bueno que todavía no hayas declarado filas como cadena [].
Animal Style
@AnimalStyle tienes razón - actualizado con un método más robusto y filas declaradas
Matt Farguson
3
Modificado de Mr ChuckBevitt
Solución de trabajo:
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);}
Entonces esto resuelve un problema de memoria ¿verdad? Este es el procesamiento línea por línea y no persiste en la memoria, por lo que no debería haber excepciones. Me gusta la forma en que se procesa, pero ¿File.ReadAllLines () no guarda todo en la memoria? Creo que se supone que debes usar File.ReadLines () para evitar un gran búfer de memoria? Esta es una buena respuesta para la pregunta en cuestión que solo quiero saber sobre las preocupaciones relacionadas con la memoria.
DtechNet
2
Aquí hay una solución que utiliza el controlador de texto ODBC de 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
Una vez rellenado, puede valorar las propiedades de la tabla de datos, como ColumnName, para utilizar todos los poderes de los objetos de datos ADO.Net.
En VS2008 puede usar Linq para lograr el mismo efecto.
NOTA: Esto puede ser un duplicado de esta pregunta SO.
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;}
Tenga en cuenta que en la versión 13Configuration se cambió el nombre a CsvConfigurationpara evitar conflictos de espacio de nombres. Demostración de esta respuesta funcionando: dotnetfiddle.net/sdwc6i
dbc
2
Utilizo una biblioteca llamada ExcelDataReader, puedes encontrarla en NuGet. Asegúrese de instalar tanto ExcelDataReader como la extensión ExcelDataReader.DataSet (esta última proporciona el método AsDataSet requerido al que se hace referencia a continuación).
Encapsulé todo en una función, puedes copiarlo en tu código directamente. Dale una ruta al archivo CSV, te da un conjunto de datos con una tabla.
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 2020 y esta es una gran solución en comparación con algunas de las respuestas anteriores aquí. Está bien empaquetado y utiliza una biblioteca popular y ligera de NuGet. Y es flexible: si su CSV está en la memoria, simplemente páselo como una MemoryStreamruta de archivo en lugar de hacerlo. El DataTable que OP solicitó se extrae fácilmente del DataSet de esta manera:result.Tables[0]
Tawab Wakil
1
Solo compartiendo estos métodos de extensión, espero que pueda ayudar a alguien.
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;}
Usar esta biblioteca para cargar a DataTablees extremadamente fácil.
using var tr =File.OpenText("data.csv");
using var dr =CsvDataReader.Create(tr);var dt =newDataTable();
dt.Load(dr);
Suponiendo que su archivo es un archivo estándar separado por comas con encabezados, eso es todo lo que necesita. También hay opciones para permitir la lectura de archivos sin encabezados y el uso de delimitadores alternativos, etc.
También es posible proporcionar un esquema personalizado para el archivo CSV para que las columnas puedan tratarse como algo distinto de los stringvalores. Esto permitirá que las DataTablecolumnas se carguen con valores que pueden ser más fáciles de trabajar, ya que no tendrá que forzarlos cuando acceda a ellos.
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);
TypedCsvSchemaes una implementación de la ICsvSchemaProvidercual proporciona una manera simple de definir los tipos de las columnas. Sin embargo, también es posible proporcionar una personalización ICsvSchemaProvidercuando desee proporcionar más metadatos, como unicidad o tamaño de columna restringido, etc.
Respuestas:
Aquí hay una clase excelente que copiará los datos CSV en una tabla de datos utilizando la estructura de los datos para crear la tabla de datos:
Un analizador genérico portátil y eficiente para archivos planos
Es fácil de configurar y fácil de usar. Te insto a que eches un vistazo.
fuente
He estado usando el
OleDb
proveedor. Sin embargo, tiene problemas si está leyendo en filas que tienen valores numéricos pero desea que se traten como texto. Sin embargo, puede solucionar ese problema creando unschema.ini
archivo. Aquí está mi método que utilicé:fuente
He decidido usar el lector de Csv de Sebastien Lorion .
La sugerencia de Jay Riggs también es una gran solución, pero no necesitaba todas las características que proporciona el analizador genérico de Andrew Rissing .
ACTUALIZACIÓN 25/10/2010
Después de usar el Lector de Csv de Sebastien Lorion en mi proyecto durante casi un año y medio, descubrí que arroja excepciones al analizar algunos archivos csv que creo que están bien formados.
Entonces, cambié al analizador genérico de Andrew Rissing y parece estar mucho mejor.
ACTUALIZACIÓN 22/09/2014
En estos días, utilizo principalmente este método de extensión para leer texto delimitado:
https://github.com/Core-Techs/Common/blob/master/CoreTechs.Common/Text/DelimitedTextExtensions.cs#L22
https://www.nuget.org/packages/CoreTechs.Common/
ACTUALIZACIÓN 20/02/2015
Ejemplo:
fuente
Hola, está funcionando al 100%
Imagen CSV
Tabla de datos importada
fuente
Siempre solíamos usar el controlador Jet.OLEDB, hasta que comenzamos a utilizar aplicaciones de 64 bits. Microsoft no ha lanzado ni lanzará un controlador Jet de 64 bits. Aquí hay una solución simple que se nos ocurrió que usa File.ReadAllLines y String.Split para leer y analizar el archivo CSV y cargar manualmente una DataTable. Como se señaló anteriormente, NO maneja la situación en la que uno de los valores de la columna contiene una coma. Usamos esto principalmente para leer archivos de configuración personalizados; lo bueno de usar archivos CSV es que podemos editarlos en Excel.
fuente
este es el código que uso, pero sus aplicaciones deben ejecutarse con la versión neta 3.5
fuente
Puede lograrlo usando Microsoft.VisualBasic.FileIO.TextFieldParser dll en C #
fuente
fuente
Me encontré con este código que usa Linq y regex para analizar un archivo CSV. El artículo de referencia ahora tiene más de un año y medio, pero no ha encontrado una forma más ordenada de analizar un CSV usando Linq (y regex) que esto. La advertencia es que la expresión regular aplicada aquí es para archivos delimitados por comas (¡detectará comas dentro de comillas!) Y que puede que no se adapte bien a los encabezados, pero hay una manera de superarlos). Toma un pico:
fuente
FileHelpers es la mejor opción que he encontrado, y resuelve problemas en los que puede tener instaladas diferentes versiones de Office, y también problemas de 32/64 bits como Chuck Bevitt .
Se puede agregar a las referencias de su proyecto usando NuGet y proporciona una solución de una sola línea:
fuente
Para aquellos de ustedes que no desean usar una biblioteca externa y prefieren no usar OleDB, consulte el siguiente ejemplo. ¡Todo lo que encontré fue OleDB, una biblioteca externa, o simplemente dividir en base a una coma! Para mi caso, OleDB no funcionaba, así que quería algo diferente.
Encontré un artículo de MarkJ que hacía referencia al método Microsoft.VisualBasic.FileIO.TextFieldParser como se ve aquí . El artículo está escrito en VB y no devuelve una tabla de datos, así que vea mi ejemplo a continuación.
fuente
Respuesta muy básica: si no tiene un csv complejo que pueda usar una función de división simple, esto funcionará bien para importar (tenga en cuenta que esto importa como cadenas, luego haré conversiones de tipo de datos si es necesario)
Mi método si estoy importando una tabla con un separador de cadena [] y maneja el problema donde la línea actual que estoy leyendo puede haber ido a la siguiente línea en el archivo csv o de texto <- EN cuyo caso quiero hacer un bucle hasta que llegue al número total de líneas en la primera fila (columnas)
fuente
Modificado de Mr ChuckBevitt
Solución de trabajo:
fuente
Aquí hay una solución que utiliza el controlador de texto ODBC de ADO.Net:
Una vez rellenado, puede valorar las propiedades de la tabla de datos, como ColumnName, para utilizar todos los poderes de los objetos de datos ADO.Net.
En VS2008 puede usar Linq para lograr el mismo efecto.
NOTA: Esto puede ser un duplicado de esta pregunta SO.
fuente
No puedo resistirme a agregar mi propio giro a esto. Esto es mucho mejor y más compacto que lo que he usado en el pasado.
Esta solución:
Esto es lo que se me ocurrió:
Depende de un método de extensión (
Unique
) para manejar nombres de columnas duplicados que se encontrarán como mi respuesta en Cómo agregar números únicos a una lista de cadenasY aquí está la
BlankToNothing
función auxiliar:fuente
Con Cinchoo ETL , una biblioteca de código abierto, puede convertir fácilmente archivos CSV a DataTable con pocas líneas de código.
Para obtener más información, visite el artículo de codeproject .
Espero eso ayude.
fuente
utilizando: https://joshclose.github.io/CsvHelper/
fuente
Configuration
se cambió el nombre aCsvConfiguration
para evitar conflictos de espacio de nombres. Demostración de esta respuesta funcionando: dotnetfiddle.net/sdwc6iUtilizo una biblioteca llamada ExcelDataReader, puedes encontrarla en NuGet. Asegúrese de instalar tanto ExcelDataReader como la extensión ExcelDataReader.DataSet (esta última proporciona el método AsDataSet requerido al que se hace referencia a continuación).
Encapsulé todo en una función, puedes copiarlo en tu código directamente. Dale una ruta al archivo CSV, te da un conjunto de datos con una tabla.
fuente
MemoryStream
ruta de archivo en lugar de hacerlo. El DataTable que OP solicitó se extrae fácilmente del DataSet de esta manera:result.Tables[0]
Solo compartiendo estos métodos de extensión, espero que pueda ayudar a alguien.
fuente
Use esto, una función resuelve todos los problemas de coma y cita:
fuente
fuente
Recientemente escribí un analizador CSV para .NET que , según afirmo, es actualmente el más rápido disponible como paquete nuget : Sylvan.Data.Csv .
Usar esta biblioteca para cargar a
DataTable
es extremadamente fácil.Suponiendo que su archivo es un archivo estándar separado por comas con encabezados, eso es todo lo que necesita. También hay opciones para permitir la lectura de archivos sin encabezados y el uso de delimitadores alternativos, etc.
También es posible proporcionar un esquema personalizado para el archivo CSV para que las columnas puedan tratarse como algo distinto de los
string
valores. Esto permitirá que lasDataTable
columnas se carguen con valores que pueden ser más fáciles de trabajar, ya que no tendrá que forzarlos cuando acceda a ellos.TypedCsvSchema
es una implementación de laICsvSchemaProvider
cual proporciona una manera simple de definir los tipos de las columnas. Sin embargo, también es posible proporcionar una personalizaciónICsvSchemaProvider
cuando desee proporcionar más metadatos, como unicidad o tamaño de columna restringido, etc.fuente