2009-09-03 23 views
34

Mi piacerebbe creare un array da un file CSV.Lettore C# CSV molto semplice

Questo è quanto di più semplice si possa immaginare, il file CSV sarà sempre e solo avere una linea e questi valori:

Device, SignalStrength, Location, Time, Age. 

mi piacerebbe mettere questi valori in una matrice bidimensionale.

Ho provato alcuni esempi ma sono stati tutti più complicati del necessario.

+3

puzza un po 'homeworky - ci mostrano quello che hai finora – annakata

+0

La "matrice monodimensionale" suona strana, sei sicuro di voler perdere le informazioni sulle interruzioni di linea? –

+0

@HenkHolterman l'OP afferma che ci sarà sempre una sola riga – KingCronus

risposta

50

Se v'è sempre e solo una riga poi fare qualcosa di simile:

using System; 
using System.IO; 

class Program 
{ 
    static void Main() 
    { 
     String[] values = File.ReadAllText(@"d:\test.csv").Split(','); 
    } 
} 
+73

No, no, no, questo è troppo complesso !! – ChaosPandion

+103

Se uno qualsiasi dei campi contiene una virgola, questo avrà esito negativo. –

+5

Come gestite le nuove linee? – nonsensickle

62

È possibile provare il qualche cosa come il sotto LINQ snippet.

string[] allLines = File.ReadAllLines(@"E:\Temp\data.csv"); 

    var query = from line in allLines 
       let data = line.Split(',') 
       select new 
       { 
        Device = data[0], 
        SignalStrength = data[1], 
        Location = data[2], 
        Time = data[3], 
        Age = Convert.ToInt16(data[4]) 
       }; 

UPDATE: Per un periodo di tempo, le cose si è evoluta. A partire da ora, preferirei usare questa libreria http://www.aspnetperformance.com/post/LINQ-to-CSV-library.aspx

+6

Ciao Ramesh .. la tua soluzione è ottima .. ma come fai a sfuggire alle virgole? – andrew0007

+0

@ andrew007 - La prima cosa che mi è venuta in mente è usare la regex per dividere. Controlla http://regexadvice.com/blogs/ wayneking/archive/2004/01/12/271.aspx – Ramesh

+14

@ramesh "Alcune persone, di fronte a un problema, pensano:" Lo so, userò le espressioni regolari ". Ora hanno due problemi. "- Jamie Zawinski. Dai uno sguardo a http://secretgeek.net/csv_trouble.asp –

7

Ecco una semplice funzione che ho fatto. Accetta una stringa CSV e restituisce una serie di campi:

Funziona bene con file CSV generati da Excel e molte altre varianti.

public static string[] ParseCsvRow(string r) 
    { 

     string[] c; 
     string t; 
     List<string> resp = new List<string>(); 
     bool cont = false; 
     string cs = ""; 

     c = r.Split(new char[] { ',' }, StringSplitOptions.None); 

     foreach (string y in c) 
     { 
      string x = y; 


      if (cont) 
      { 
       // End of field 
       if (x.EndsWith("\"")) 
       { 
        cs += "," + x.Substring(0, x.Length - 1); 
        resp.Add(cs); 
        cs = ""; 
        cont = false; 
        continue; 

       } 
       else 
       { 
        // Field still not ended 
        cs += "," + x; 
        continue; 
       } 
      } 

      // Fully encapsulated with no comma within 
      if (x.StartsWith("\"") && x.EndsWith("\"")) 
      { 
       if ((x.EndsWith("\"\"") && !x.EndsWith("\"\"\"")) && x != "\"\"") 
       { 
        cont = true; 
        cs = x; 
        continue; 
       } 

       resp.Add(x.Substring(1, x.Length - 2)); 
       continue; 
      } 

      // Start of encapsulation but comma has split it into at least next field 
      if (x.StartsWith("\"") && !x.EndsWith("\"")) 
      { 
       cont = true; 
       cs += x.Substring(1); 
       continue; 
      } 

      // Non encapsulated complete field 
      resp.Add(x); 

     } 

     return resp.ToArray(); 

    } 
+1

fallisce quando avere cell1, "cell2", ",,,,,,,,", "precedente fallisce" – MurWade

3

Questo è quello che ho usato in un progetto, analizza una singola riga di dati.

private string[] csvParser(string csv, char separator = ',') 
    { 
     List <string> = new <string>(); 
     string[] temp = csv.Split(separator); 
     int counter = 0; 
     string data = string.Empty; 
     while (counter < temp.Length) 
     { 
      data = temp[counter].Trim(); 
      if (data.Trim().StartsWith("\"")) 
      { 
       bool isLast = false; 
       while (!isLast && counter < temp.Length) 
       { 
        data += separator.ToString() + temp[counter + 1]; 
        counter++; 
        isLast = (temp[counter].Trim().EndsWith("\"")); 
       } 
      } 
      parsed.Add(data); 
      counter++; 
     } 

     return parsed.ToArray(); 

    } 

http://zamirsblog.blogspot.com/2013/09/c-csv-parser-csvparser.html

+0

Penso che la riga 3 dovrebbe leggere: Elenco analizzato = nuovo Elenco (); – Matiaan

+0

Bel tentativo ma purtroppo non riesce con un " out of array boundary "eccezione sui dati di linea + = separator.ToString() + temp [contatore + 1]; su una linea ben formata :( – AFract

2

La mia soluzione gestisce le citazioni, sul campo e stringa imperativi separatori, ecc E 'breve e dolce.

public static string[] CSVRowToStringArray(string r, char fieldSep = ',', char stringSep = '\"') 
    { 
     bool bolQuote = false; 
     StringBuilder bld = new StringBuilder(); 
     List<string> retAry = new List<string>(); 

     foreach (char c in r.ToCharArray()) 
      if ((c == fieldSep && !bolQuote)) 
      { 
       retAry.Add(bld.ToString()); 
       bld.Clear(); 
      } 
      else 
       if (c == stringSep) 
        bolQuote = !bolQuote; 
       else 
        bld.Append(c); 

     return retAry.ToArray(); 
    } 
+0

Questa soluzione sembra perdere l'ultimo valore sulla linea, anche su un test molto semplice con nessuna citazione – AFract

3

Questa versione fissa del codice sopra ricordate l'ultimo elemento di CVS fila ;-)

(testato con un file CSV con 5400 righe e 26 elementi per riga)

public static string[] CSVRowToStringArray(string r, char fieldSep = ',', char stringSep = '\"') { 
      bool bolQuote = false; 
      StringBuilder bld = new StringBuilder(); 
      List<string> retAry = new List<string>(); 

      foreach (char c in r.ToCharArray()) 
       if ((c == fieldSep && !bolQuote)) 
       { 
        retAry.Add(bld.ToString()); 
        bld.Clear(); 
       } 
       else 
        if (c == stringSep) 
         bolQuote = !bolQuote; 
        else 
         bld.Append(c); 

      /* to solve the last element problem */ 
      retAry.Add(bld.ToString()); /* added this line */ 
      return retAry.ToArray(); 
     } 
-1

Prima di tutti hanno bisogno di capire cos'è il CSV e come scriverlo.

  1. Ogni stringa successiva (/r/n) è la riga successiva "tabella".
  2. Le celle "Tabella" sono separate da un simbolo delimitatore. Il più delle volte utilizzati simboli è \t o ,
  3. Ogni cellula, eventualmente, può contenere questo simbolo delimitatore (cella deve iniziare con le citazioni simbolo e si conclude con questo simbolo in questo caso)
  4. Ogni cellula, eventualmente, può contenere /r/n sybols (cella deve a iniziare con citazioni simbolo e si conclude con questo simbolo in questo caso)

semplice classe Qualche tempo fa avevo scritto per il CSV di lettura/scrittura basato sullo standard Microsoft.VisualBasic.FileIO biblioteca. Usando questa semplice classe sarai in grado di lavorare con CSV come con una matrice di 2 dimensioni.

semplice esempio di utilizzo di mia biblioteca:

Csv csv = new Csv("\t");//delimiter symbol 

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

var row1Cell6Value = csv.Rows[0][5]; 

csv.AddRow("asdf","asdffffff","5") 

csv.FileSave("c:\\file2.csv"); 

Si può trovare la mia classe dal seguente link e indagare su come è scritto: https://github.com/ukushu/DataExporter

Problemi correlati