CSV-bestand lezen en waarden opslaan in een array

Ik probeer een *.csv-bestand te lezen.

Het *.csv-bestand bestaat uit twee kolommen gescheiden door puntkomma’s (“;“).

Ik kan het *.csv-bestand lezen met StreamReader en ik kan elke regel scheiden met de functie Split(). Ik wil elke kolom in een afzonderlijke array opslaan en deze vervolgens weergeven.

Is het mogelijk om dat te doen?


Antwoord 1, autoriteit 100%

Je kunt het als volgt doen:

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

Antwoord 2, autoriteit 44%

Mijn favoriete CSV-parser is er een die is ingebouwd in de .NET-bibliotheek. Dit is een verborgen schat in de naamruimte Microsoft.VisualBasic.
Hieronder staat een voorbeeldcode:

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

Vergeet niet om een verwijzing naar Microsoft.VisualBasic

toe te voegen

Meer details over de parser worden hier gegeven: http://codeskaters.blogspot.ae/2015/11/c-easiest-csv-parser-built-in-net.html


Antwoord 3, autoriteit 16%

LINQ manier:

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

^^Fout – Bewerkt door Nick

Het lijkt erop dat de oorspronkelijke antwoorder probeerde csvte vullen met een tweedimensionale array – een array die arrays bevat. Elk item in de eerste array bevat een array die dat regelnummer vertegenwoordigt, waarbij elk item in de geneste array de gegevens voor die specifieke kolom bevat.

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

Antwoord 4, autoriteit 8%

Ik kwam zojuist deze bibliotheek tegen: https://github.com/JoshClose/CsvHelper

Zeer intuïtief en gemakkelijk te gebruiken. Heeft ook een nuget-pakket dat snel te implementeren is: http://nuget.org/packages/CsvHelper/1.17.0. Lijkt ook actief te worden onderhouden, wat ik leuk vind.

Het configureren om een puntkomma te gebruiken is eenvoudig: https://github.com/JoshClose/CsvHelper/ wiki/Aangepaste configuraties


Antwoord 5, autoriteit 8%

U kunt een array niet onmiddellijk maken omdat u het aantal rijen vanaf het begin moet weten (en dit zou het CSV-bestand twee keer moeten lezen)

U kunt waarden opslaan in twee List<T>en gebruik ze dan of converteren in een array met List<T>.ToArray()

Zeer eenvoudig voorbeeld:

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.

Houd er rekening mee dat dit slechts een zeer eenvoudig voorbeeld is. Met string.SplitWordt niet verantwoordelijk voor gevallen waarin sommige records het scheider bevatten ;erin.
Voor een veiliger benadering, overweeg dan wat CSV-specifieke bibliotheken zoals CSVHelper op Nuget.


Antwoord 6, Autoriteit 7%

Ik gebruik dit meestal parser van codeproject , omdat er een stel karakter ontsnapt en vergelijkbaar is handvatten voor mij.


Antwoord 7, Autoriteit 6%

Hier is mijn variatie van de top gestemd antwoord:

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

De csvVariabele kan vervolgens worden gebruikt zoals in het volgende voorbeeld:

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

Antwoord 8, autoriteit 2%

Als u (kop-)regels en/of kolommen moet overslaan, kunt u dit gebruiken om een 2-dimensionale array te maken:

   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

Dit is erg handig als u de gegevens vorm moet geven voordat u ze verder verwerkt (ervan uitgaande dat de eerste 2 regels uit de kop bestaan en de eerste kolom een rijtitel is – die u niet in de array hoeft te hebben omdat u alleen de gegevens wilt bekijken).

N.B.U kunt eenvoudig de koppen en de 1e kolom krijgen door de volgende code te gebruiken:

   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

Dit codevoorbeeld gaat uit van de volgende structuur van uw *.csv-bestand:

Opmerking:als u lege rijen moet overslaan – wat soms handig kan zijn, kunt u dit doen door in te voegen

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

tussen de fromen de selectinstructie in de LINQcodevoorbeelden hierboven.


Antwoord 9, autoriteit 2%

Je kunt Microsoft.VisualBasic.FileIO.TextFieldParser dll in C# gebruiken voor betere prestaties

haal onderstaand codevoorbeeld uit bovenstaand artikel

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

Antwoord 10

Hallo allemaal, ik heb hiervoor een statische klasse gemaakt.
+ kolomcontrole
+ verwijdering van quotateken

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

Antwoord 11

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

Antwoord 12

Ik heb een paar uur doorbreng op zoek naar een rechterbibliotheek, maar eindelijk schreef ik mijn eigen code 🙂
U kunt bestand (of database) lezen met welke tools u ook wilt en vervolgens de volgende routine op elke regel toepassen:

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

Antwoord 13

Hier is een speciaal geval waarin een van het gegevensveld een puntkomma (“;”) heeft als onderdeel van zijn gegevens in dat geval in dat geval zal de meeste antwoorden hierboven mislukken.

Oplossing IT DAT CASE ZELT

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

Antwoord 14

De open-source angara.table bibliotheek maakt het mogelijk om CSV in getypte te laden kolommen, zodat u de arrays uit de kolommen kunt krijgen. Elke kolom kan zowel op naam of index worden geïndexeerd. Zie http://predictionMachines.github.io/angara.table/sAndoad.html.

De bibliotheek volgt RFC4180 voor CSV; Het maakt typegespinning en multiline-snaren mogelijk.

Voorbeeld:

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

U kunt een kolomtype bekijken met behulp van de kolom Type, b.g

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

Aangezien de bibliotheek op F # is gericht, moet u mogelijk een verwijzing toevoegen aan de FSHARP.Core 4.4 Assembly; Klik op ‘Referentie toevoegen’ in het project en kies Fsharp.core 4.4 onder “Assemblies” – & GT; “Extensions”.


Antwoord 15

Ik gebruik CSVReader.com (betaalde component) al jaren, en ik heb nog nooit een probleem gehad. Het is solide, klein en snel, maar je moet ervoor betalen. U kunt de scheidingsteken instellen op wat u maar wilt.

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

Antwoord 16

Ik ben maar een student die aan mijn masterscriptie werkt, maar dit is de manier waarop ik het heb opgelost en het werkte goed voor mij. Eerst selecteert u uw bestand uit de directory (alleen in csv-formaat) en vervolgens plaatst u de gegevens in de lijsten.

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

Antwoord 17

Mijn eenvoudige statische methoden om CSV-lijn naar array en array naar CSV-lijn te converteren.

public static string CsvRowFromStringArray(string[] csvData, char fieldSeparator = ',', char stringQuote = '"')
{
    csvData = csvData.Select(element => {
        if (element.Contains(stringQuote))
        {
            element = element.Replace(stringQuote.ToString(), stringQuote.ToString() + stringQuote.ToString());
        }
        if (element.Contains(fieldSeparator))
        {
            element = "\"" + element + "\"";
        }
        return element;
    }).ToArray();
    return string.Join(fieldSeparator.ToString(), csvData);
}
public static string[] CsvRowToStringArray(string csvRow, char fieldSeparator = ',', char stringQuote = '"')
{
    char tempQuote = (char)162;
    while (csvRow.Contains(tempQuote)) { tempQuote = (char)(tempQuote + 1); }
    char tempSeparator = (char)(tempQuote + 1);
    while (csvRow.Contains(tempSeparator)) { tempSeparator = (char)(tempSeparator + 1); }
    csvRow = csvRow.Replace(stringQuote.ToString() + stringQuote.ToString(), tempQuote.ToString());
    var csvArray = csvRow.Split(fieldSeparator).ToList().Aggregate("",
        (string row, string item) =>
        {
            if (row.Count((ch) => ch == stringQuote) % 2 == 0) { return row + (row.Length > 0 ? tempSeparator.ToString() : "") + item; }
            else { return row + fieldSeparator + item; }
        },
        (string row) => row.Split(tempSeparator).Select((string item) => item.Trim(stringQuote).Replace(tempQuote, stringQuote))).ToArray();
    return csvArray;
}
private bool CsvTestError()
{
    string correctString = "0;a;\"b; c\";\"\"xy;\"this;is; one \"\"long; cell\"\"\"";
    string[] correctArray = new string[] { "0", "a", "b; c", "\"xy", "this;is; one \"long; cell\"" };
    bool error = string.Join("°", CsvRowToStringArray(correctString, ';')) != string.Join("°", correctArray);
    error = (CsvRowFromStringArray(correctArray, ';') != correctString) || error;
    return error;
}

Antwoord 18

Nog steeds fout. U moet compenseren voor “” tussen aanhalingstekens.
Hier is mijn oplossing Microsoft-stijl 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;
    }
}

Antwoord 19

Ik heb een bibliotheek die je precies doet.

Enige tijd geleden had ik eenvoudig en snel genoeg bibliotheek geschreven voor werk met CSV-bestanden. U kunt het vinden op de volgende link: https://github.com/ukushu/dataExporter

Het werkt met CSV zoals met 2 dimensions array. Precies zoals je nodig hebt.

Als voorbeeld, in het geval dat u alle waarden van de 3e rij alleen nodig hebt, hoeft u alleen te schrijven:

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

of om de 2e cel van

te lezen

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

Antwoord 20

Kijk hierna

met behulp van CsvFramework;

met behulp van System.Collections.Generic;

naamruimte CvsParser
{

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Order> Orders { get; set; }        
}
public class Order
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public int Quantity { get; set; }
    public int Amount { get; set; }
    public List<OrderItem> OrderItems { get; set; }
}
public class Address
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public string Name { get; set; }
}
public class OrderItem
{
    public int Id { get; set; }
    public int OrderId { get; set; }
    public string ProductName { get; set; }
}
class Program
{
    static void Main(string[] args)
    {
        var customerLines = System.IO.File.ReadAllLines(@"Customers.csv");
        var orderLines = System.IO.File.ReadAllLines(@"Orders.csv");
        var orderItemLines = System.IO.File.ReadAllLines(@"OrderItemLines.csv");
        CsvFactory.Register<Customer>(builder =>
        {
            builder.Add(a => a.Id).Type(typeof(int)).Index(0).IsKey(true);
            builder.Add(a => a.Name).Type(typeof(string)).Index(1);
            builder.AddNavigation(n => n.Orders).RelationKey<Order, int>(k => k.CustomerId);
        }, false, ',', customerLines);
        CsvFactory.Register<Order>(builder =>
        {
            builder.Add(a => a.Id).Type(typeof(int)).Index(0).IsKey(true);
            builder.Add(a => a.CustomerId).Type(typeof(int)).Index(1);
            builder.Add(a => a.Quantity).Type(typeof(int)).Index(2);
            builder.Add(a => a.Amount).Type(typeof(int)).Index(3);
            builder.AddNavigation(n => n.OrderItems).RelationKey<OrderItem, int>(k => k.OrderId);
        }, true, ',', orderLines);
        CsvFactory.Register<OrderItem>(builder =>
        {
            builder.Add(a => a.Id).Type(typeof(int)).Index(0).IsKey(true);
            builder.Add(a => a.OrderId).Type(typeof(int)).Index(1);
            builder.Add(a => a.ProductName).Type(typeof(string)).Index(2);
        }, false, ',', orderItemLines);
        var customers = CsvFactory.Parse<Customer>();
    }
}

}

Other episodes