web-dev-qa-db-fra.com

Lecture/écriture de fichiers CSV/délimités par des tabulations en c #

J'ai besoin de lire à partir d'un fichier CSV/Tab délimité et d'écrire dans un tel fichier également à partir de .net.

Le problème est que je ne connais pas la structure de chaque fichier et que je dois écrire le fichier cvs/tab dans un fichier datatable, ce que la bibliothèque FileHelpers ne semble pas prendre en charge.

Je l'ai déjà écrit pour Excel avec OLEDB, mais je ne vois pas vraiment comment écrire un fichier de tabulation à cet effet. Nous allons donc revenir à une bibliothèque.

Quelqu'un peut-il aider avec des suggestions?

13
Tim Almond

J'ai utilisé ce CsvReader , il est vraiment génial et bien configurable. Il se comporte bien avec toutes sortes d'échappements pour les chaînes et les séparateurs. Les échappements dans d'autres implémentations rapides et sales étaient médiocres, mais cette bibliothèque est vraiment géniale en lecture. Avec quelques lignes de code supplémentaires, vous pouvez également ajouter un cache si vous en avez besoin.

L'écriture n'est pas prise en charge, mais il est plutôt facile de mettre en œuvre vous-même. Ou inspirez-vous de ce code .

8
jdehaan

.NET est livré avec un analyseur de fichier délimité par un fichier CSV/tab appelé la classe TextFieldParser.

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

Il prend en charge l'intégralité de la RFC pour les fichiers CSV et un très bon rapport d'erreurs.

13
Jonathan Allen

Voici quelques implémentations de lecteurs CSV:

http://www.codeproject.com/KB/database/CsvReader.aspx

http://www.heikniemi.fi/jhlib/ (juste une partie de la bibliothèque; inclut également un graveur CSV)

Je doute qu'il existe un moyen standard de convertir CSV en DataTable ou base de données "automatiquement", vous devrez écrire du code pour le faire. Comment faire cela est une question distincte.

1
Qwertie

Vous allez créer votre datatable dans le code et (en supposant une ligne d'en-tête), vous pouvez créer des colonnes en fonction de votre première ligne du fichier. Après cela, il suffira simplement de lire le fichier et de créer de nouvelles lignes en fonction des données qu'il contient.

Vous pouvez utiliser quelque chose comme ceci:

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

Le code ci-dessus n'a pas été compilé, donc il peut avoir quelques erreurs, mais il devrait vous mettre sur la bonne voie.

1
AllenG

Eh bien, il existe une autre bibliothèque Cinchoo ETL - une bibliothèque open source pour la lecture et l’écriture de fichiers CSV.

Deux façons de lire des fichiers CSV

Id, Name
1, Tom
2, Mark

Voici comment utiliser cette bibliothèque pour la lire

using (var reader = new ChoCSVReader("emp.csv").WithFirstLineHeader())
{
   foreach (dynamic item in reader)
   {
      Console.WriteLine(item.Id);
      Console.WriteLine(item.Name);
   }
}

Si un objet POCO est défini pour correspondre au fichier CSV, comme ci-dessous

public class Employee
{
   public int Id { get; set; }
   public string Name { get; set; }
}

Vous pouvez analyser le même fichier en utilisant cette classe POCO comme ci-dessous

using (var reader = new ChoCSVReader<Employee>("emp.csv").WithFirstLineHeader())
{
   foreach (var item in reader)
   {
      Console.WriteLine(item.Id);
      Console.WriteLine(item.Name);
   }
}

S'il vous plaît consulter les articles à CodeProject sur la façon de l'utiliser.

Disclaimer: je suis l'auteur de cette bibliothèque

0
RajN

J'ai trouvé la meilleure solution

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

Juste je devais ré-écrire

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
        }
    }
}
0
Salim

Vous pouvez lire et écrire des fichiers csv .. Cela peut vous être utile.

passe le caractère divisé à ce paramètre "serparationChar"

Exemple : -

    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

Exemple simple avec CsvHelper

using (TextWriter writer = new StreamWriter(filePath)
{
    var csvWriter = new CsvWriter(writer);
    csvWriter.Configuration.Delimiter = "\t";
    csvWriter.Configuration.Encoding = Encoding.UTF8;
    csvWriter.WriteRecords(exportRecords); 
}
0
Wieslaw Olborski