it-swarm.com.de

CSV-Datei lesen und Werte in einem Array speichern

Ich versuche eine *.csv- Datei zu lesen.

Die *.csv- Datei besteht aus zwei Spalten, die durch Semikolon ("; ") getrennt sind. 

Ich kann die *.csv- Datei mit StreamReader lesen und jede Zeile mit der Funktion Split() trennen. Ich möchte jede Spalte in einem separaten Array speichern und dann anzeigen. 

Kann man das machen?

252
Rushabh Shah

Sie können es so machen:

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]);
        }
    }
}
323
Michael M.

Mein liebster CSV-Parser ist ein in die .net-Bibliothek integrierter. Dies ist ein verborgener Schatz im Microsoft.VisualBasic-Namespace . Nachfolgend finden Sie einen Beispielcode:

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

Denken Sie daran, einen Verweis auf Microsoft.VisualBasic hinzuzufügen.

Weitere Informationen zum Parser finden Sie hier: http://codeskaters.blogspot.ae/2015/11/c-easiest-csv-parser-built-in-net.html

113
Habeeb

LINQ-Weg: 

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

^^ Falsch - Edit by Nick

Es scheint, dass der ursprüngliche Antworter versucht hat, csv mit einem zweidimensionalen Array zu füllen - einem Array, das Arrays enthält. Jedes Element im ersten Array enthält ein Array, das diese Zeilennummer darstellt, wobei jedes Element im verschachtelten Array die Daten für diese bestimmte Spalte enthält.

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

Normalerweise verwende ich diesen Parser von codeproject , da es eine Reihe von Zeichenfluchtzeichen und ähnliches gibt, die für mich verarbeitet werden.

32
Paul

Hier ist meine Variante der am besten bewerteten Antwort:

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

Die Variable csv kann dann wie im folgenden Beispiel verwendet werden:

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

Ich bin gerade auf diese Bibliothek gestoßen: https://github.com/JoshClose/CsvHelper

Sehr intuitiv und einfach zu bedienen. Hat auch ein Nuget-Paket, das sich schnell implementieren lässt: http://nuget.org/packages/CsvHelper/1.17.0 . Scheint auch aktiv gewartet zu werden was mir gefällt.

Die Konfiguration eines Semikolons ist einfach: https://github.com/JoshClose/CsvHelper/wiki/Custom-Configurations

26
joshb

Sie können ein Array nicht sofort erstellen, da Sie die Anzahl der Zeilen von Anfang an kennen müssen (dazu müsste die CSV-Datei zweimal gelesen werden).

Sie können Werte in zwei List<T> speichern und dann verwenden oder in ein Array mit List<T>.ToArray() konvertieren.

Sehr einfaches Beispiel:

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

N.B.

Bitte beachten Sie, dass dies nur ein sehr einfaches Beispiel ist. Die Verwendung von string.Split berücksichtigt nicht die Fälle, in denen einige Datensätze das Trennzeichen ; enthalten.
Für einen sichereren Ansatz sollten Sie einige CSV-spezifische Bibliotheken wie CsvHelper für Nuget verwenden.

24
digEmAll

Wenn Sie (Kopf-) Zeilen und/oder Spalten überspringen müssen, können Sie dies zum Erstellen eines 2-dimensionalen Arrays verwenden:

    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

Dies ist sehr nützlich, wenn Sie die Daten vor der weiteren Verarbeitung in Form bringen müssen (vorausgesetzt, die ersten beiden Zeilen bestehen aus der Überschrift und die erste Spalte ist ein Zeilentitel die Daten betrachten wollen).

N.B. Sie können die Überschriften und die 1. Spalte leicht aufrufen, indem Sie folgenden Code verwenden:

    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

Dieses Codebeispiel setzt die folgende Struktur Ihrer *.csv-Datei voraus:

CSV Matrix

Hinweis: Wenn Sie leere Zeilen überspringen müssen - was manchmal nützlich ist, können Sie dies durch Einfügen tun

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

zwischen der from- und der select-Anweisung in den obigen CodebeispielenLINQ.

11
Matt

Sie können Microsoft.VisualBasic.FileIO.TextFieldParser-DLL in C # verwenden, um die Leistung zu verbessern 

code-Beispiel aus dem obigen Artikel erhalten

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;
}
9
kombsh

Hallo zusammen, ich habe eine statische Klasse erstellt, um dies zu tun . + Spaltenüberprüfung + Entfernen von Quotenzeichen

public static class CSV
{
    public static List<string[]> Import(string file, char csvDelimiter, bool ignoreHeadline, bool removeQuoteSign)
    {
        return ReadCSVFile(file, csvDelimiter, ignoreHeadline, removeQuoteSign);
    }

    private static List<string[]> ReadCSVFile(string filename, char csvDelimiter, bool ignoreHeadline, bool removeQuoteSign)
    {
        string[] result = new string[0];
        List<string[]> lst = new List<string[]>();

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

}
4
Mathias Schmidt

Hier ist ein Sonderfall, in dem eines der Datenfelder ein Semikolon (";") als Teil seiner Daten enthält. In diesem Fall schlagen die meisten der obigen Antworten fehl.

Lösung wird dieser Fall sein 

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(); 
}
4
Yogesh
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();
3
Jakub Konecki

Die Open-Source Angara.Table - Bibliothek ermöglicht das Laden von CSV in typisierte Spalten, sodass Sie die Arrays aus den Spalten erhalten können. Jede Spalte kann sowohl nach Name als auch nach Index indiziert werden. Siehe http://predictionmachines.github.io/Angara.Table/saveload.html .

Die Bibliothek folgt RFC4180 für CSV; Es ermöglicht Typeninferenz und mehrzeilige Zeichenketten.

Beispiel:

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<double> a = table["double-column-name"].Rows.AsReal;

for(int i = 0; i < a.Length; i++)
{
    Console.WriteLine("{0}: {1}", i, a[i]);
}

Sie können einen Spaltentyp mit dem Typ Spalte sehen, z.

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

Da sich die Bibliothek auf F # konzentriert, müssen Sie möglicherweise einen Verweis auf die FSharp.Core 4.4-Assembly hinzufügen. Klicken Sie im Projekt auf "Verweis hinzufügen" und wählen Sie "FSharp.Core 4.4" unter "Assemblies" -> "Extensions".

Ich arbeite nur an meiner Masterarbeit, aber so habe ich sie gelöst und es hat gut für mich funktioniert. Zuerst wählen Sie Ihre Datei aus dem Verzeichnis aus (nur im CSV-Format) und geben Sie dann die Daten in die Listen ein.

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
        );
    }
}
1
Daniel

Ich verwende seit Jahren csvreader.com (kostenpflichtige Komponente) und hatte noch nie ein Problem. Es ist solide, klein und schnell, aber Sie müssen dafür bezahlen. Sie können das Trennzeichen beliebig einstellen.

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] ...
}
1
Oliver Bock

Immer noch falsch. Sie müssen "" in Anführungszeichen "" kompensieren. ".

               /// <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;
    }
}
0
R Keene

Ich habe ein paar Stunden damit verbracht, nach einer richtigen Bibliothek zu suchen, aber schließlich habe ich meinen eigenen Code geschrieben :) Sie können die Datei (oder Datenbank) mit beliebigen Tools lesen und dann die folgende Routine auf jede Zeile anwenden:

private static string[] SmartSplit(string line, char separator = ',')
{
    var inQuotes = false;
    var token = "";
    var lines = new List<string>();
    for (var i = 0; i < line.Length; i++) {
        var ch = line[i];
        if (inQuotes) // process string in quotes, 
        {
            if (ch == '"') {
                if (i<line.Length-1 && line[i + 1] == '"') {
                    i++;
                    token += '"';
                }
                else inQuotes = false;
            } else token += ch;
        } else {
            if (ch == '"') inQuotes = true;
            else if (ch == separator) {
                lines.Add(token);
                token = "";
                } else token += ch;
            }
    }
    lines.Add(token);
    return lines.ToArray();
}
0
Zbyszek Swirski

Ich habe eine Bibliothek, die genau das tut, was Sie brauchen.

Vor einiger Zeit hatte ich eine einfache und schnell genug Bibliothek für die Arbeit mit CSV-Dateien geschrieben. Sie finden es unter folgendem Link: https://github.com/ukushu/DataExporter

Es funktioniert mit CSV wie mit einem zweidimensionalen Array. Genau so, wie Sie es brauchen.

Wenn Sie beispielsweise alle Werte der dritten Zeile benötigen, müssen Sie nur schreiben:

Csv csv = new Csv();

csv.FileOpen("c:\\file1.csv");

var allValuesOf3rdRow = csv.Rows[2];

oder 2. Zelle von lesen 

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