Lendo arquivo CSV e armazenando valores em uma matriz

Eu estou tentando ler um arquivo *.csv .

O arquivo *.csv consiste em duas colunas separadas por ponto e vírgula (” ; “).

Eu sou capaz de ler o arquivo *.csv usando StreamReader e capaz de separar cada linha usando a function Split() . Eu quero armazenar cada coluna em uma matriz separada e, em seguida, exibi-lo.

É possível fazer isso?

Você pode fazer assim:

 using System.IO; static void Main(string[] args) { using(var reader = new StreamReader(@"C:\test.csv")) { List listA = new List(); List listB = new List(); while (!reader.EndOfStream) { var line = reader.ReadLine(); var values = line.Split(';'); listA.Add(values[0]); listB.Add(values[1]); } } } 

Meu analisador csv favorito é um construído na biblioteca .net. Este é um tesouro escondido dentro do namespace Microsoft.VisualBasic. Abaixo está um código de exemplo:

 using Microsoft.VisualBasic.FileIO; var path = @"C:\Person.csv"; // Habeeb, "Dubai Media City, Dubai" using (TextFieldParser csvParser = new TextFieldParser(path)) { csvParser.CommentTokens = new string[] { "#" }; csvParser.SetDelimiters(new string[] { "," }); csvParser.HasFieldsEnclosedInQuotes = true; // Skip the row with the column names csvParser.ReadLine(); while (!csvParser.EndOfData) { // Read current line fields, pointer moves to the next line. string[] fields = csvParser.ReadFields(); string Name = fields[0]; string Address = fields[1]; } } 

Lembre-se de adicionar referência ao Microsoft.VisualBasic

Mais detalhes sobre o analisador são fornecidos aqui: http://codeskaters.blogspot.ae/2015/11/c-easiest-csv-parser-built-in-net.html

LINQ maneira:

 var lines = File.ReadAllLines("test.txt").Select(a => a.Split(';')); var csv = from line in lines select (from piece in line select piece); 

^^ Errado – Editar por Nick

Parece que o respondente original estava tentando preencher csv com uma matriz bidimensional – uma matriz contendo matrizes. Cada item na primeira matriz contém uma matriz que representa esse número de linha com cada item na matriz aninhada que contém os dados dessa coluna específica.

 var csv = from line in lines select (line.Split(',')).ToArray(); 

Eu costumo usar este analisador de código de projeto , uma vez que há um monte de personagem escapa e semelhante que ele manipula para mim.

Aqui está a minha variação da resposta mais votada:

 var contents = File.ReadAllText(filename).Split('\n'); var csv = from line in contents select line.Split(',').ToArray(); 

A variável csv pode então ser usada como no exemplo a seguir:

 int headerRows = 5; foreach (var row in csv.Skip(headerRows) .TakeWhile(r => r.Length > 1 && r.Last().Trim().Length > 0)) { String zerothColumnValue = row[0]; // leftmost column var firstColumnValue = row[1]; } 

Acabei de encontrar esta biblioteca: https://github.com/JoshClose/CsvHelper

Muito intuitivo e fácil de usar. Também tem um pacote nuget que é rápido de implementar: http://nuget.org/packages/CsvHelper/1.17.0 . Também parece ser mantido ativamente que eu gosto.

Configurá-lo para usar um ponto e vírgula é fácil: https://github.com/JoshClose/CsvHelper/wiki/Custom-Configurations

Você não pode criar uma matriz imediatamente porque precisa saber o número de linhas desde o início (e isso exigiria ler o arquivo csv duas vezes)

Você pode armazenar valores em dois List e usá-los ou convertê-los em um array usando List.ToArray()

Exemplo muito simples:

 var column1 = new List(); var column2 = new List(); using (var rd = new StreamReader("filename.csv")) { while (!rd.EndOfStream) { var splits = rd.ReadLine().Split(';'); column1.Add(splits[0]); column2.Add(splits[1]); } } // print column1 Console.WriteLine("Column 1:"); foreach (var element in column1) Console.WriteLine(element); // print column2 Console.WriteLine("Column 2:"); foreach (var element in column2) Console.WriteLine(element); 

Se você precisar pular (head-) linhas e / ou colunas, você pode usar isso para criar uma matriz bidimensional:

  var lines = File.ReadAllLines(path).Select(a => a.Split(';')); var csv = (from line in lines select (from col in line select col).Skip(1).ToArray() // skip the first column ).Skip(2).ToArray(); // skip 2 headlines 

Isso é bastante útil se você precisar modelar os dados antes de processá-los (supondo que as duas primeiras linhas consistam no título e a primeira coluna seja um título de linha – o que você não precisa ter na matriz porque você acabou de quero considerar os dados).

NB Você pode facilmente obter as manchetes e a primeira coluna usando o seguinte código:

  var coltitle = (from line in lines select line.Skip(1).ToArray() // skip 1st column ).Skip(1).Take(1).FirstOrDefault().ToArray(); // take the 2nd row var rowtitle = (from line in lines select line[0] // take 1st column ).Skip(2).ToArray(); // skip 2 headlines 

Este exemplo de código pressupõe a seguinte estrutura do seu arquivo *.csv :

Matriz CSV

Nota: Se você precisar pular linhas vazias – o que pode ser prático às vezes, você pode fazer isso inserindo

  where line.Any(a=>!string.IsNullOrWhiteSpace(a)) 

entre a instrução from e select nos exemplos de código LINQ acima.

Você pode usar Microsoft.VisualBasic.FileIO.TextFieldParser dll em c # para melhor desempenho

obter abaixo exemplo de código do artigo acima

 static void Main() { string csv_file_path=@"C:\Users\Administrator\Desktop\test.csv"; DataTable csvData = GetDataTabletFromCSVFile(csv_file_path); Console.WriteLine("Rows count:" + csvData.Rows.Count); Console.ReadLine(); } private static DataTable GetDataTabletFromCSVFile(string csv_file_path) { DataTable csvData = new DataTable(); try { using(TextFieldParser csvReader = new TextFieldParser(csv_file_path)) { csvReader.SetDelimiters(new string[] { "," }); csvReader.HasFieldsEnclosedInQuotes = true; string[] colFields = csvReader.ReadFields(); foreach (string column in colFields) { DataColumn datecolumn = new DataColumn(column); datecolumn.AllowDBNull = true; csvData.Columns.Add(datecolumn); } while (!csvReader.EndOfData) { string[] fieldData = csvReader.ReadFields(); //Making empty value as null for (int i = 0; i < fieldData.Length; i++) { if (fieldData[i] == "") { fieldData[i] = null; } } csvData.Rows.Add(fieldData); } } } catch (Exception ex) { } return csvData; } 

Aqui está um caso especial em que um dos campos de dados tem ponto-e-vírgula (“;”) como parte de seus dados. Nesse caso, a maioria das respostas acima falhará.

Solução que esse caso será

 string[] csvRows = System.IO.File.ReadAllLines(FullyQaulifiedFileName); string[] fields = null; List lstFields; string field; bool quoteStarted = false; foreach (string csvRow in csvRows) { lstFields = new List(); field = ""; for (int i = 0; i < csvRow.Length; i++) { string tmp = csvRow.ElementAt(i).ToString(); if(String.Compare(tmp,"\"")==0) { quoteStarted = !quoteStarted; } if (String.Compare(tmp, ";") == 0 && !quoteStarted) { lstFields.Add(field); field = ""; } else if (String.Compare(tmp, "\"") != 0) { field += tmp; } } if(!string.IsNullOrEmpty(field)) { lstFields.Add(field); field = ""; } // This will hold values for each column for current row under processing fields = lstFields.ToArray(); } 
 var firstColumn = new List(); var lastColumn = new List(); // your code for reading CSV file foreach(var line in file) { var array = line.Split(';'); firstColumn.Add(array[0]); lastColumn.Add(array[1]); } var firstArray = firstColumn.ToArray(); var lastArray = lastColumn.ToArray(); 

Oi pessoal Eu criei uma class estática para fazer isso. + verificação de coluna + remoção de sinal de cota

 public static class CSV { public static List Import(string file, char csvDelimiter, bool ignoreHeadline, bool removeQuoteSign) { return ReadCSVFile(file, csvDelimiter, ignoreHeadline, removeQuoteSign); } private static List ReadCSVFile(string filename, char csvDelimiter, bool ignoreHeadline, bool removeQuoteSign) { string[] result = new string[0]; List lst = new List(); string line; int currentLineNumner = 0; int columnCount = 0; // Read the file and display it line by line. using (System.IO.StreamReader file = new System.IO.StreamReader(filename)) { while ((line = file.ReadLine()) != null) { currentLineNumner++; string[] strAr = line.Split(csvDelimiter); // save column count of dirst line if (currentLineNumner == 1) { columnCount = strAr.Count(); } else { //Check column count of every other lines if (strAr.Count() != columnCount) { throw new Exception(string.Format("CSV Import Exception: Wrong column count in line {0}", currentLineNumner)); } } if (removeQuoteSign) strAr = RemoveQouteSign(strAr); if (ignoreHeadline) { if(currentLineNumner !=1) lst.Add(strAr); } else { lst.Add(strAr); } } } return lst; } private static string[] RemoveQouteSign(string[] ar) { for (int i = 0;i< ar.Count() ; i++) { if (ar[i].StartsWith("\"") || ar[i].StartsWith("'")) ar[i] = ar[i].Substring(1); if (ar[i].EndsWith("\"") || ar[i].EndsWith("'")) ar[i] = ar[i].Substring(0,ar[i].Length-1); } return ar; } } 

A biblioteca Angara.Table de código aberto permite carregar CSV em colunas digitadas, para que você possa obter as matrizes das colunas. Cada coluna pode ser indexada por nome ou índice. Veja http://predictionmachines.github.io/Angara.Table/saveload.html .

A biblioteca segue a RFC4180 para CSV; ele permite inferência de tipos e strings de múltiplas linhas.

Exemplo:

 using System.Collections.Immutable; using Angara.Data; using Angara.Data.DelimitedFile; ... ReadSettings settings = new ReadSettings(Delimiter.Semicolon, false, true, null, null); Table table = Table.Load("data.csv", settings); ImmutableArray a = table["double-column-name"].Rows.AsReal; for(int i = 0; i < a.Length; i++) { Console.WriteLine("{0}: {1}", i, a[i]); } 

Você pode ver um tipo de coluna usando o tipo Coluna, por exemplo

 Column c = table["double-column-name"]; Console.WriteLine("Column {0} is double: {1}", c.Name, c.Rows.IsRealColumn); 

Como a biblioteca é focada em F #, talvez seja necessário adicionar uma referência ao assembly FSharp.Core 4.4; clique em 'Add Reference' no projeto e escolha FSharp.Core 4.4 em "Assemblies" -> "Extensions".

Eu tenho usado csvreader.com (componente pago) por anos, e nunca tive um problema. É sólido, pequeno e rápido, mas você tem que pagar por isso. Você pode definir o delimitador para o que quiser.

 using (CsvReader reader = new CsvReader(s) { reader.Settings.Delimiter = ';'; reader.ReadHeaders(); // if headers on a line by themselves. Makes reader.Headers[] available while (reader.ReadRecord()) ... use reader.Values[col_i] ... } 

Ainda errado. Você precisa compensar “” entre aspas. Aqui está a minha solução csv estilo da Microsoft.

  ///  /// Microsoft style csv file. " is the quote character, "" is an escaped quote. ///  ///  ///  ///  ///  ///  public static List ReadCSVFileMSStyle(string fileName, char sepChar = ',', char quoteChar = '"') { List ret = new List(); string[] csvRows = System.IO.File.ReadAllLines(fileName); foreach (string csvRow in csvRows) { bool inQuotes = false; List fields = new List(); string field = ""; for (int i = 0; i < csvRow.Length; i++) { if (inQuotes) { // Is it a "" inside quoted area? (escaped litteral quote) if(i < csvRow.Length - 1 && csvRow[i] == quoteChar && csvRow[i+1] == quoteChar) { i++; field += quoteChar; } else if(csvRow[i] == quoteChar) { inQuotes = false; } else { field += csvRow[i]; } } else // Not in quoted region { if (csvRow[i] == quoteChar) { inQuotes = true; } if (csvRow[i] == sepChar) { fields.Add(field); field = ""; } else { field += csvRow[i]; } } } if (!string.IsNullOrEmpty(field)) { fields.Add(field); field = ""; } ret.Add(fields.ToArray()); } return ret; } } 

Eu sou apenas estudante trabalhando na minha tese de mestrado, mas esta é a maneira que eu resolvi e funcionou bem para mim. Primeiro você seleciona seu arquivo do diretório (somente no formato csv) e depois coloca os dados nas listas.

 List t = new List(); List SensorI = new List(); List SensorII = new List(); List SensorIII = new List(); using (OpenFileDialog dialog = new OpenFileDialog()) { try { dialog.Filter = "csv files (*.csv)|*.csv"; dialog.Multiselect = false; dialog.InitialDirectory = "."; dialog.Title = "Select file (only in csv format)"; if (dialog.ShowDialog() == DialogResult.OK) { var fs = File.ReadAllLines(dialog.FileName).Select(a => a.Split(';')); int counter = 0; foreach (var line in fs) { counter++; if (counter > 2) // Skip first two headder lines { this.t.Add(float.Parse(line[0])); this.SensorI.Add(float.Parse(line[1])); this.SensorII.Add(float.Parse(line[2])); this.SensorIII.Add(float.Parse(line[3])); } } } } catch (Exception exc) { MessageBox.Show( "Error while opening the file.\n" + exc.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error ); } } 

Eu tenho uma biblioteca que está fazendo exatamente o que você precisa.

Algum tempo atrás eu tinha escrito biblioteca simples e rápida o suficiente para trabalhar com arquivos CSV. Você pode encontrá-lo pelo seguinte link: https://github.com/ukushu/DataExporter

Funciona com o CSV como com array de 2 dimensões. Exatamente como você precisa.

Por exemplo, no caso de você precisar de todos os valores da terceira linha, só precisa escrever:

 Csv csv = new Csv(); csv.FileOpen("c:\\file1.csv"); var allValuesOf3rdRow = csv.Rows[2]; 

ou para ler a segunda célula de

 var value = csv.Rows[2][1];