c# asp - Leyendo el archivo CSV y almacenando valores en una matriz




net read (15)

Estoy tratando de leer un archivo *.csv .

El archivo *.csv consta de dos columnas separadas por punto y coma (" ; ").

Puedo leer el archivo *.csv usando StreamReader y puedo separar cada línea usando la función Split() . Quiero almacenar cada columna en una matriz separada y luego mostrarla.

¿Es posible hacer eso?


Answers

Mi analizador csv favorito es uno integrado en la biblioteca .net. Este es un tesoro escondido dentro del espacio de nombres Microsoft.VisualBasic. A continuación se muestra un código de ejemplo:

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];
 }
}

Recuerde agregar referencia a Microsoft.VisualBasic

Más detalles sobre el analizador se dan aquí: http://codeskaters.blogspot.ae/2015/11/c-easiest-csv-parser-built-in-net.html


Puedes hacerlo así:

using System.IO;

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

            listA.Add(values[0]);
            listB.Add(values[1]);
        }
    }
}

Solo soy un estudiante que está trabajando en mi tesis de maestría, pero esta es la forma en que la resolví y funcionó bien para mí. Primero seleccione su archivo del directorio (solo en formato csv) y luego coloque los datos en las listas.

List<float> t = new List<float>();
List<float> SensorI = new List<float>();
List<float> SensorII = new List<float>();
List<float> SensorIII = new List<float>();
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
        );
    }
}


He estado usando csvreader.com (componente de pago) durante años, y nunca he tenido un problema. Es sólido, pequeño y rápido, pero tienes que pagarlo. Puedes configurar el delimitador a lo que quieras.

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] ...
}

Si necesita omitir (encabezados) líneas y / o columnas, puede usar esto para crear una 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

Esto es bastante útil si necesita dar forma a los datos antes de continuar procesándolos (asumiendo que las primeras 2 líneas consisten en el título, y la primera columna es un título de fila, que no necesita tener en la matriz porque simplemente Quiero tener en cuenta los datos).

NB Puede obtener fácilmente los titulares y la primera columna utilizando el siguiente 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 ejemplo de código asume la siguiente estructura de su archivo *.csv :

Nota: Si necesita omitir filas vacías, lo que a veces puede ser útil, puede hacerlo insertando

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

entre la declaración from y la select en los ejemplos de código LINQ anteriores.


Aquí hay un caso especial en el que uno de los campos de datos tiene un punto y coma (";") como parte de sus datos; en ese caso, la mayoría de las respuestas anteriores fallarán.

Solución es que ese caso será

string[] csvRows = System.IO.File.ReadAllLines(FullyQaulifiedFileName);
string[] fields = null;
List<string> lstFields;
string field;
bool quoteStarted = false;
foreach (string csvRow in csvRows)
{
    lstFields = new List<string>();
    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(); 
}

Aquí está mi variación de la respuesta más votada:

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

La variable csv se puede usar como en el siguiente ejemplo:

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];
}

var firstColumn = new List<string>();
var lastColumn = new List<string>();

// 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();

Sigue siendo incorrecto. Necesitas compensar por "" entre comillas. Aquí está mi solución de estilo Microsoft csv.

               /// <summary>
    /// Microsoft style csv file.  " is the quote character, "" is an escaped quote.
    /// </summary>
    /// <param name="fileName"></param>
    /// <param name="sepChar"></param>
    /// <param name="quoteChar"></param>
    /// <param name="escChar"></param>
    /// <returns></returns>
    public static List<string[]> ReadCSVFileMSStyle(string fileName, char sepChar = ',', char quoteChar = '"')
    {
        List<string[]> ret = new List<string[]>();

        string[] csvRows = System.IO.File.ReadAllLines(fileName);

        foreach (string csvRow in csvRows)
        {
            bool inQuotes = false;
            List<string> fields = new List<string>();
            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;
    }
}


Puede usar Microsoft.VisualBasic.FileIO.TextFieldParser dll en C # para un mejor rendimiento

Obtener el ejemplo de código de abajo del artículo anterior

static void Main()
{
    string [email protected]"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;
}

No puede crear una matriz inmediatamente porque necesita saber la cantidad de filas desde el principio (y esto requeriría leer el archivo csv dos veces)

Puede almacenar valores en dos List<T> y luego usarlos o convertirlos en una matriz utilizando List<T>.ToArray()

Ejemplo muy simple:

var column1 = new List<string>();
var column2 = new List<string>();
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);

Forma LINQ:

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

^^ Incorrecto - Editado por Nick

Parece que el contestador original estaba intentando rellenar csv con una matriz bidimensional, una matriz que contiene matrices. Cada elemento de la primera matriz contiene una matriz que representa ese número de línea con cada elemento de la matriz anidada que contiene los datos para esa columna específica.

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

Este es un iterador para la lista no dispersa donde el índice comienza en 0, que es el escenario típico cuando se trata de document.getElementsByTagName o document.querySelectorAll)

function each( fn, data ) {

    if(typeof fn == 'string')
        eval('fn = function(data, i){' + fn + '}');

    for(var i=0, L=this.length; i < L; i++) 
        fn.call( this[i], data, i );   

    return this;
}

Array.prototype.each = each;  

Ejemplos de uso:

Ejemplo 1

var arr = [];
[1, 2, 3].each( function(a){ a.push( this * this}, arr);
arr = [1, 4, 9]

Ejemplo # 2

each.call(document.getElementsByTagName('p'), "this.className = data;",'blue');

Cada etiqueta p obtiene class="blue"

Ejemplo # 3

each.call(document.getElementsByTagName('p'), 
    "if( i % 2 == 0) this.className = data;",
    'red'
);

Cada otra etiqueta p obtiene class="red">

Ejemplo # 4

each.call(document.querySelectorAll('p.blue'), 
    function(newClass, i) {
        if( i < 20 )
            this.className = newClass;
    }, 'green'
);

Y finalmente, las primeras 20 etiquetas p azules se cambian a verde.

Precaución al usar la cadena como función: la función se crea fuera de contexto y debe usarse solo cuando esté seguro del alcance de la variable. De lo contrario, es mejor pasar funciones donde el alcance es más intuitivo.







c# .net arrays csv