2010-06-28 44 views
13

Ho bisogno di leggere da un file delimitato da CSV/Tab e scrivere su un file come pure da .net.Lettura/scrittura di file CSV/delimitati da tabulazione in C#

La difficoltà è che non conosco la struttura di ogni file e ho bisogno di scrivere il file cvs/tab su un datatable, che la libreria FileHelpers non sembra supportare.

L'ho già scritto per Excel usando OLEDB, ma non riesco davvero a vedere un modo per scrivere un file di tabulazioni per questo, quindi tornerò in una libreria.

Qualcuno può aiutare con suggerimenti?

risposta

7

Ho usato questo CsvReader, è davvero eccezionale e ben configurabile. Si comporta bene con tutti i tipi di escape per stringhe e separatori. La fuga in altre implementazioni rapide e sporche era scarsa, ma questa lettura è davvero eccezionale. Con alcune linee di codice aggiuntive è anche possibile aggiungere una cache se necessario.

La scrittura non è supportata ma è piuttosto banale implementarla. Oppure ispirati allo this code.

+0

Scusa .. mi sembra un po 'distante, ma credo che la mia considerazione principale con la scrittura di file CSV sia la delimitazione delle stringhe (è passato un po' di tempo dal momento che dovevo fare file CSV). –

+0

Ho aggiunto un collegamento per la scrittura CSV, è possibile sostituire alcune stringhe costanti con il delimitatore preferito e dovrebbe essere ok. Leggere è molto più complicato della scrittura ... – jdehaan

+0

Ma scrivere file CSV che contengono stringhe arbitrarie non è banale. Ricorda le sequenze di fuga! –

1

Creerai il tuo datatable in codice e (presumendo una riga di intestazione) puoi creare colonne basate sulla tua prima riga nel file. Dopodiché, si tratterà semplicemente di leggere il file e creare nuove righe in base ai dati in esso contenuti.

si potrebbe usare qualcosa di simile:

DataTable Tbl = new DataTable(); 
using(StreamReader sr = new StreamReader(path)) 
{ 
    int count = 0; 
    string headerRow = sr.Read(); 
    string[] headers = headerRow.split("\t") //Or "," 
    foreach(string h in headers) 
    { 
    DataColumn dc = new DataColumn(h); 
    Tbl.Columns.Add(dc); 
    count++; 
    } 
    while(sr.Peek()) 
    { 
    string data = sr.Read(); 
    string[] cells = data.Split("\t") 
    DataRow row = new DataRow(); 
    foreach(string c in cells) 
    { 
     row.Columns.Add(c); 
    } 
    Tbl.Rows.Add(row); 
    } 
} 

Il codice di cui sopra non è stato compilato, quindi potrebbe avere alcuni errori, ma dovrebbe arrivare sulla strada giusta.

+0

Il tuo codice split è sbagliato, in quanto potresti avere il demiliator in una stringa quotata. –

+0

@ Jonathan Allen: Sì, davvero si può. Non è stato progettato per essere la soluzione completa ... solo un puntatore a una possibile traccia giusta. – AllenG

13

.NET viene fornito con un parser di file delimitatore CSV/tab denominato classe TextFieldParser.

http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.fileio.textfieldparser.aspx

Essa sostiene la piena RFC per i file CSV e davvero buona la segnalazione degli errori.

+5

Devi amare che le classi di utilità generali sono in Microsoft.VisualBasic.dll. – MgSam

+0

Sfortunatamente questo non sembra supportare specificando il proprio carattere di text wrapping, si presume che questo sia un doppio apice e ti permetta solo di accendere/spegnere. – ChrisProsser

+1

Potresti fornire un esempio veloce? I collegamenti non sono risposte sufficienti. Se si rompe questa risposta è inutile per qualsiasi googler. –

0

È possibile leggere e scrivere file CSV .. Questo potrebbe essere utile.

passaggio diviso char a questo parametro "serparationChar"

Esempio: -

private DataTable dataTable = null; 
    private bool IsHeader = true; 
    private string headerLine = string.Empty; 
    private List<string> AllLines = new List<string>(); 
    private StringBuilder sb = new StringBuilder(); 
    private char seprateChar = ','; 


    public DataTable ReadCSV(string path, bool IsReadHeader, char serparationChar) 
    { 
     seprateChar = serparationChar; 
     IsHeader = IsReadHeader; 
     using (StreamReader sr = new StreamReader(path,Encoding.Default)) 
     { 
      while (!sr.EndOfStream) 
      { 
       AllLines.Add(sr.ReadLine()); 
      } 
      createTemplate(AllLines); 
     } 

     return dataTable; 
    } 
    public void WriteCSV(string path,DataTable dtable,char serparationChar) 
    { 
     AllLines = new List<string>(); 
     seprateChar = serparationChar; 
     List<string> StableHeadrs = new List<string>(); 
     int colCount = 0; 
     using (StreamWriter sw = new StreamWriter(path)) 
     { 
      foreach (DataColumn col in dtable.Columns) 
      { 
       sb.Append(col.ColumnName); 
       if(dataTable.Columns.Count-1 > colCount) 
       sb.Append(seprateChar); 
       colCount++; 
      } 
      AllLines.Add(sb.ToString()); 

      for (int i = 0; i < dtable.Rows.Count; i++) 
      { 
       sb.Clear(); 
       for (int j = 0; j < dtable.Columns.Count; j++) 
       { 
        sb.Append(Convert.ToString(dtable.Rows[i][j])); 
        if (dataTable.Columns.Count - 1 > j) 
        sb.Append(seprateChar); 
       } 
       AllLines.Add(sb.ToString()); 
      } 

      foreach (string dataline in AllLines) 
      { 
       sw.WriteLine(dataline); 
      } 
     } 


    } 

    private DataTable createTemplate(List<string> lines) 
    { 

     List<string> headers = new List<string>(); 
     dataTable = new DataTable(); 
     if (lines.Count > 0) 
     { 
      string[] argHeaders = null; 
      for (int i = 0; i < lines.Count; i++) 
      { 
       if (i > 0) 
       { 
        DataRow newRow = dataTable.NewRow(); 
        // others add to rows 
        string[] argLines = lines[i].Split(seprateChar); 
        for (int b = 0; b < argLines.Length; b++) 
        { 
         newRow[b] = argLines[b]; 
        } 
        dataTable.Rows.Add(newRow); 

       } 
       else 
       { 
        // header add to columns 
        argHeaders = lines[0].Split(seprateChar); 
        foreach (string c in argHeaders) 
        { 
         DataColumn column = new DataColumn(c, typeof(string)); 
         dataTable.Columns.Add(column); 
        } 
       } 

      } 

     } 
     return dataTable; 
    } 
0

ho trovato migliore soluzione

http://www.codeproject.com/Articles/415732/Reading-and-Writing-CSV-Files-in-Csharp

Proprio ho dovuto re-scrittura

void ReadTest() 
{ 
    // Read sample data from CSV file 
    using (CsvFileReader reader = new CsvFileReader("ReadTest.csv")) 
    { 
     CsvRow row = new CsvRow(); 
     while (reader.ReadRow(row)) 
     { 
      foreach (string s in row) 
      { 
       Console.Write(s); 
       Console.Write(" "); 
      } 
      Console.WriteLine(); 

      row = new CsvRow(); //this line added 
     } 
    } 
} 
Problemi correlati