Excelente mesmo. Funcionou perfeitamente para mim imediatamente, sem sequer ler a documentação.
Smirkingman 29/05
Isso funcionará em arquivos CSV, onde cada linha pode ter uma estrutura diferente? Eu tenho um arquivo de log com diferentes tipos de eventos registrados que precisariam ser separados em várias tabelas.
gonzobrains
2
@gonzobrains - Provavelmente não; a suposição básica de um arquivo CSV é uma estrutura de dados retangular com base em um único conjunto de cabeçalhos de coluna especificados na primeira linha. O que você tem parece ser mais dados genéricos, separados por vírgula e discriminados, exigindo "ETL" mais sofisticado para analisar do arquivo em instâncias de objetos de vários tipos (que podem incluir DataRows de diferentes DataTables).
Keiths
93
Eu tenho usado OleDbprovedor. No entanto, há problemas se você estiver lendo em linhas que possuem valores numéricos, mas deseja que eles sejam tratados como texto. No entanto, você pode solucionar esse problema criando um schema.iniarquivo. Aqui está o meu método que eu usei:
// 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;}}
Obrigado parceiro. Isso me ajudou. Eu tinha um arquivo CSV no qual vírgulas não eram apenas separadoras, elas estavam em todos os lugares dentro de muitos valores de colunas; portanto, criar um regex que dividisse a linha era meio desafiador. O OleDbProvider inferiu o esquema corretamente.
Galilyou
A implementação faz sentido, mas como lidamos com células que contêm tipos de dados mistos. Por exemplo, 40C e etc.?
GKED
GKED, se os dados em que você está lendo sempre tiver um conjunto esperado de colunas e tipos, você poderá colocar na mesma pasta um arquivo shema.ini que informe ao provedor OleDb informações sobre as colunas. Aqui está um link para um artigo da Microsoft que fornece detalhes de como estruturar o arquivo. msdn.microsoft.com/en-us/library/…
Jim Scott
4
Embora essa resposta funcione, eu desaconselharia fortemente. Você introduz uma dependência externa que pode entrar em conflito com outras instalações do office na mesma máquina (use o Excel no seu ambiente de desenvolvimento local?), Dependendo das versões instaladas. Existem pacotes NuGet por aí (ExcelDataReader, CsvHelper) que fazem isso de maneiras mais eficientes e portáteis.
A. Murray
1
@ A.Murray - O que exatamente você quer dizer? Isso usa o provedor OleDb interno no System.Data.dll. Você não precisa instalar nenhum "driver" adicional. E eu ficaria chocado hoje em dia se alguma instalação do Windows não tivesse o driver Jet básico instalado. Este é 1990 CSV ....
A sugestão de Jay Riggs também é uma ótima solução, mas eu simplesmente não precisava de todos os recursos que o Analisador Genérico de Andrew Rissing fornece.
ATUALIZAÇÃO 10/25/2010
Depois de usar o Csv Reader de Sebastien Lorion em meu projeto por quase um ano e meio, descobri que ele lança exceções ao analisar alguns arquivos csv que acredito serem bem 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());}
Concordo que o leitor de CSV de Sebastien Lorien é ótimo. Eu o uso para processamento pesado de CSV, mas também usei o Andrew's Rissing para pequenos trabalhos e isso me serviu bem. Diverta-se!
21419 Jay Riggs #
Como posso usar essas classes para carregar o CSV no DATATABLE?
Muflix
Eu tentei isso, mas a coleção it.Current.Keys retorna com "System.Linq.Enumerable + WhereSelectListIterator`2 [System.Int32, System.Char]" em vez do nome da coluna. Alguma ideia do por quê?
user3658298
Você pode usar delimitadores de vários caracteres?
rola
Não, mas pensei em permitir isso.
precisa saber é o seguinte
32
Ei, está trabalhando 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 eu estou recebendo o erro na última linha você está aí, em seguida, dar-lhe outras informações de contato
Sunil Acharya
Embora eu não tenha usado essa versão exatamente, foi com base nela que resolvi meu problema. Obrigado. Funciona muito bem.
Nrod 23/11
13
Sempre usamos o driver Jet.OLEDB, até começarmos a acessar aplicativos de 64 bits. A Microsoft não lançou e não lançará um driver Jet de 64 bits. Aqui está uma solução simples que criamos que usa File.ReadAllLines e String.Split para ler e analisar o arquivo CSV e carregar manualmente um DataTable. Como observado acima, ele NÃO lida com a situação em que um dos valores da coluna contém uma vírgula. Usamos isso principalmente para ler arquivos de configuração personalizados - a parte boa sobre o uso de arquivos CSV é que podemos editá-los no 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 é o código que eu o uso, mas seus aplicativos devem ser executados com a versão 3.5 da rede
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 deparei com esse pedaço de código que usa Linq e regex para analisar um arquivo CSV. O artigo de referência agora tem mais de um ano e meio, mas não encontrou uma maneira mais clara de analisar um CSV usando Linq (e regex) além disso. A ressalva é que o regex aplicado aqui é para arquivos delimitados por vírgula (detectará vírgulas entre aspas!) E que pode não ser bom para os cabeçalhos, mas existe uma maneira de superá-los. Dê um 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
A melhor opção que encontrei e resolve problemas em que você pode ter diferentes versões do Office instaladas, além de problemas de 32/64 bits como Chuck Bevitt mencionado , é o FileHelpers .
Ele pode ser adicionado às referências do seu projeto usando o NuGet e fornece uma solução de uma linha:
você pode dizer o que é o CommonEngine? O NuGet é o mesmo do NuGet.Core. I encontrado apenas NuGet.Core em referências
sindhu jampani
É FileHelpers que você precisa. Se você possui o NuGet, adicione-o ao NuGet. Caso contrário, basta adicioná-lo como uma montagem em seu projeto. O CommonEngine faz parte do FileHelpers.
Neo
3
Para aqueles que desejam não usar uma biblioteca externa e preferem não usar o OleDB, veja o exemplo abaixo. Tudo o que encontrei foi o OleDB, a biblioteca externa ou simplesmente a divisão com base em vírgula! Para o meu caso, o OleDB não estava funcionando, então eu queria algo diferente.
Encontrei um artigo de MarkJ que referenciava o método Microsoft.VisualBasic.FileIO.TextFieldParser como visto aqui . O artigo está escrito em VB e não retorna uma tabela de dados, portanto, veja meu exemplo abaixo.
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;}
Resposta muito básica: se você não tiver um csv complexo que possa usar uma função de divisão simples, isso funcionará bem para importação (observe que isso importa como seqüências de caracteres, eu faço conversões de tipo de dados mais tarde, se necessário)
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;}
Meu método, se estou importando uma tabela com um separador de seqüência de caracteres [] e lida com o problema em que a linha atual que estou lendo pode ter ido para a próxima linha no arquivo csv ou de texto <- IN, caso em que quero fazer um loop até obter para o número total de linhas na primeira linha (colunas)
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;}
É bom que você não tenha declarado linhas como string [] ainda.
Animal Style
@AnimalStyle você está certo - atualizado com método mais robusto e linhas declarou
Matt Farguson
3
Modificado de Mr ChuckBevitt
Solução de trabalho:
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);}
Então isso resolve um problema de memória, certo? Isso é processamento linha por linha e não persiste na memória, portanto não deve haver exceções? Eu gosto da maneira como isso é processado, mas o File.ReadAllLines () salva tudo na memória? Eu acho que você deveria usar File.ReadLines () para evitar um enorme buffer de memória? Esta é uma boa resposta para a pergunta em questão que eu só quero saber sobre problemas de memória.
DtechNet
2
Aqui está uma solução que usa o driver de texto ODBC do 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
Depois de preenchido, você pode avaliar as propriedades da tabela de dados, como ColumnName, para utilizar todos os poderes dos objetos de dados ADO.Net.
No VS2008, você pode usar o Linq para obter o mesmo efeito.
NOTA: Isso pode ser uma duplicata desta questão de 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;}
Observe que na versão 13Configuration foi renomeada CsvConfigurationpara evitar conflitos de espaço para nome. Demonstração desta resposta de trabalho: dotnetfiddle.net/sdwc6i
DBC
2
Eu uso uma biblioteca chamada ExcelDataReader, você pode encontrá-la no NuGet. Certifique-se de instalar o ExcelDataReader e a extensão ExcelDataReader.DataSet (esta última fornece o método AsDataSet necessário mencionado abaixo).
Eu encapsulei tudo em uma função, você pode copiá-lo diretamente no seu código. Dê um caminho para o arquivo CSV, ele fornece um conjunto de dados com uma tabela.
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();}}
É 2020 e esta é uma ótima solução em comparação com algumas das respostas mais antigas aqui. É bem embalado e usa uma biblioteca popular e leve da NuGet. E é flexível - se o seu CSV estiver na memória, simplesmente passe-o como um MemoryStreamcaminho em vez de como um arquivo. O DataTable solicitado pelo OP é facilmente extraído do DataSet assim:result.Tables[0]
Tawab Wakil
1
Apenas compartilhando esses métodos de extensão, espero que possa ajudar alguém.
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 carregar um DataTableé extremamente fácil.
using var tr =File.OpenText("data.csv");
using var dr =CsvDataReader.Create(tr);var dt =newDataTable();
dt.Load(dr);
Supondo que seu arquivo seja um arquivo separado por vírgula padrão com cabeçalhos, é tudo o que você precisa. Também existem opções para permitir a leitura de arquivos sem cabeçalhos e o uso de delimitadores alternativos etc.
Também é possível fornecer um esquema personalizado para o arquivo CSV, para que as colunas possam ser tratadas como algo diferente de stringvalores. Isso permitirá que as DataTablecolunas sejam carregadas com valores que possam ser mais fáceis de trabalhar, pois você não precisará coagi-los quando acessá-los.
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);
TypedCsvSchema é uma implementação de ICsvSchemaProvider que fornece uma maneira simples de definir os tipos de colunas. No entanto, também é possível fornecer um costume ICsvSchemaProviderquando você deseja fornecer mais metadados, como exclusividade ou tamanho da coluna restrita, etc.
Respostas:
Aqui está uma excelente classe que copiará dados CSV em uma tabela de dados usando a estrutura dos dados para criar o DataTable:
Um analisador genérico portátil e eficiente para arquivos simples
É fácil de configurar e fácil de usar. Peço que você dê uma olhada.
fonte
Eu tenho usado
OleDb
provedor. No entanto, há problemas se você estiver lendo em linhas que possuem valores numéricos, mas deseja que eles sejam tratados como texto. No entanto, você pode solucionar esse problema criando umschema.ini
arquivo. Aqui está o meu método que eu usei:fonte
Decidi usar o Csv Reader de Sebastien Lorion .
A sugestão de Jay Riggs também é uma ótima solução, mas eu simplesmente não precisava de todos os recursos que o Analisador Genérico de Andrew Rissing fornece.
ATUALIZAÇÃO 10/25/2010
Depois de usar o Csv Reader de Sebastien Lorion em meu projeto por quase um ano e meio, descobri que ele lança exceções ao analisar alguns arquivos csv que acredito serem bem formados.
Então, mudei para o Generic Parser de Andrew Rissing e parece estar indo muito melhor.
ATUALIZAÇÃO 22/09/2014
Hoje em dia, uso principalmente esse método de extensão para ler texto delimitado:
https://github.com/Core-Techs/Common/blob/master/CoreTechs.Common/Text/DelimitedTextExtensions.cs#L22
https://www.nuget.org/packages/CoreTechs.Common/
ATUALIZAÇÃO 20/02/2015
Exemplo:
fonte
Ei, está trabalhando 100%
Imagem CSV
Tabela de dados Importada
fonte
Sempre usamos o driver Jet.OLEDB, até começarmos a acessar aplicativos de 64 bits. A Microsoft não lançou e não lançará um driver Jet de 64 bits. Aqui está uma solução simples que criamos que usa File.ReadAllLines e String.Split para ler e analisar o arquivo CSV e carregar manualmente um DataTable. Como observado acima, ele NÃO lida com a situação em que um dos valores da coluna contém uma vírgula. Usamos isso principalmente para ler arquivos de configuração personalizados - a parte boa sobre o uso de arquivos CSV é que podemos editá-los no Excel.
fonte
este é o código que eu o uso, mas seus aplicativos devem ser executados com a versão 3.5 da rede
fonte
Você pode conseguir isso usando a DLL Microsoft.VisualBasic.FileIO.TextFieldParser em C #
fonte
fonte
Me deparei com esse pedaço de código que usa Linq e regex para analisar um arquivo CSV. O artigo de referência agora tem mais de um ano e meio, mas não encontrou uma maneira mais clara de analisar um CSV usando Linq (e regex) além disso. A ressalva é que o regex aplicado aqui é para arquivos delimitados por vírgula (detectará vírgulas entre aspas!) E que pode não ser bom para os cabeçalhos, mas existe uma maneira de superá-los. Dê um pico:
fonte
A melhor opção que encontrei e resolve problemas em que você pode ter diferentes versões do Office instaladas, além de problemas de 32/64 bits como Chuck Bevitt mencionado , é o FileHelpers .
Ele pode ser adicionado às referências do seu projeto usando o NuGet e fornece uma solução de uma linha:
fonte
Para aqueles que desejam não usar uma biblioteca externa e preferem não usar o OleDB, veja o exemplo abaixo. Tudo o que encontrei foi o OleDB, a biblioteca externa ou simplesmente a divisão com base em vírgula! Para o meu caso, o OleDB não estava funcionando, então eu queria algo diferente.
Encontrei um artigo de MarkJ que referenciava o método Microsoft.VisualBasic.FileIO.TextFieldParser como visto aqui . O artigo está escrito em VB e não retorna uma tabela de dados, portanto, veja meu exemplo abaixo.
fonte
Resposta muito básica: se você não tiver um csv complexo que possa usar uma função de divisão simples, isso funcionará bem para importação (observe que isso importa como seqüências de caracteres, eu faço conversões de tipo de dados mais tarde, se necessário)
Meu método, se estou importando uma tabela com um separador de seqüência de caracteres [] e lida com o problema em que a linha atual que estou lendo pode ter ido para a próxima linha no arquivo csv ou de texto <- IN, caso em que quero fazer um loop até obter para o número total de linhas na primeira linha (colunas)
fonte
Modificado de Mr ChuckBevitt
Solução de trabalho:
fonte
Aqui está uma solução que usa o driver de texto ODBC do ADO.Net:
Depois de preenchido, você pode avaliar as propriedades da tabela de dados, como ColumnName, para utilizar todos os poderes dos objetos de dados ADO.Net.
No VS2008, você pode usar o Linq para obter o mesmo efeito.
NOTA: Isso pode ser uma duplicata desta questão de SO.
fonte
Não resisto a adicionar minha própria rotação a isso. Isso é muito melhor e mais compacto do que o que eu usei no passado.
Esta solução:
Aqui está o que eu vim com:
Depende de um método de extensão (
Unique
) para lidar com nomes de colunas duplicados, como minha resposta em Como anexar números exclusivos a uma lista de cadeiasE aqui está a
BlankToNothing
função auxiliar:fonte
Com o Cinchoo ETL - uma biblioteca de código aberto, você pode converter facilmente arquivos CSV em DataTable com poucas linhas de código.
Para mais informações, visite codeproject artigo .
Espero que ajude.
fonte
usando: https://joshclose.github.io/CsvHelper/
fonte
Configuration
foi renomeadaCsvConfiguration
para evitar conflitos de espaço para nome. Demonstração desta resposta de trabalho: dotnetfiddle.net/sdwc6iEu uso uma biblioteca chamada ExcelDataReader, você pode encontrá-la no NuGet. Certifique-se de instalar o ExcelDataReader e a extensão ExcelDataReader.DataSet (esta última fornece o método AsDataSet necessário mencionado abaixo).
Eu encapsulei tudo em uma função, você pode copiá-lo diretamente no seu código. Dê um caminho para o arquivo CSV, ele fornece um conjunto de dados com uma tabela.
fonte
MemoryStream
caminho em vez de como um arquivo. O DataTable solicitado pelo OP é facilmente extraído do DataSet assim:result.Tables[0]
Apenas compartilhando esses métodos de extensão, espero que possa ajudar alguém.
fonte
Use isso, uma função resolve todos os problemas de vírgula e cita:
fonte
fonte
Recentemente, escrevi um analisador de CSV para .NET que estou afirmando ser atualmente o mais rápido disponível como pacote de nuget : Sylvan.Data.Csv .
Usar esta biblioteca para carregar um
DataTable
é extremamente fácil.Supondo que seu arquivo seja um arquivo separado por vírgula padrão com cabeçalhos, é tudo o que você precisa. Também existem opções para permitir a leitura de arquivos sem cabeçalhos e o uso de delimitadores alternativos etc.
Também é possível fornecer um esquema personalizado para o arquivo CSV, para que as colunas possam ser tratadas como algo diferente de
string
valores. Isso permitirá que asDataTable
colunas sejam carregadas com valores que possam ser mais fáceis de trabalhar, pois você não precisará coagi-los quando acessá-los.TypedCsvSchema
é uma implementação deICsvSchemaProvider
que fornece uma maneira simples de definir os tipos de colunas. No entanto, também é possível fornecer um costumeICsvSchemaProvider
quando você deseja fornecer mais metadados, como exclusividade ou tamanho da coluna restrita, etc.fonte