213 votes

Comment lire un fichier CSV dans une table de données .NET ?

Comment charger un fichier CSV dans une table de données System.Data.DataTable, en créant la table de données sur la base du fichier CSV ?

Existe-t-il une bibliothèque de classes pour cela ou puis-je utiliser ADO.net pour me connecter au fichier ?

29 votes

Comment cela peut-il être "hors sujet" ? C'est une question spécifique et 100 personnes la trouvent utile.

12 votes

@Ryan : En vérité je vous le dis... Les modérateurs de StackOverflow sont une couvée de vipères. Restez derrière moi, modérateurs de StackOverflow !

109voto

Jim Scott Points 1139

J'ai utilisé OleDb fournisseur. Cependant, il pose des problèmes si vous lisez des lignes qui ont l'apparence de valeurs numériques mais que vous voulez qu'elles soient traitées comme du texte. Cependant, vous pouvez contourner ce problème en créant un fichier schema.ini fichier. Voici la méthode que j'ai utilisée :

// using System.Data;
// using System.Data.OleDb;
// using System.Globalization;
// using System.IO;

static DataTable GetDataTableFromCsv(string path, bool isFirstRowHeader)
{
    string header = isFirstRowHeader ? "Yes" : "No";

    string pathOnly = Path.GetDirectoryName(path);
    string fileName = Path.GetFileName(path);

    string sql = @"SELECT * FROM [" + fileName + "]";

    using(OleDbConnection connection = new OleDbConnection(
              @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + pathOnly + 
              ";Extended Properties=\"Text;HDR=" + header + "\""))
    using(OleDbCommand command = new OleDbCommand(sql, connection))
    using(OleDbDataAdapter adapter = new OleDbDataAdapter(command))
    {
        DataTable dataTable = new DataTable();
        dataTable.Locale = CultureInfo.CurrentCulture;
        adapter.Fill(dataTable);
        return dataTable;
    }
}

0 votes

Merci, mon pote. Cela m'a aidé. J'avais un fichier CSV dans lequel les virgules n'étaient pas seulement des séparateurs, elles étaient partout dans les valeurs de plusieurs colonnes, donc trouver une regex qui couperait la ligne était un peu difficile. Le OleDbProvider a déduit le schéma correctement.

0 votes

La mise en œuvre est logique, mais comment traiter les cellules contenant des types de données mixtes. Par exemple, 40C et etc.

0 votes

GKED, si les données que vous lisez ont toujours un ensemble attendu de colonnes et de types, vous pouvez placer dans le même dossier un fichier shema.ini qui donne au fournisseur OleDb des informations sur les colonnes. Voici un lien vers un article de Microsoft qui fournit des détails sur la façon de structurer le fichier. msdn.microsoft.com/fr/us/library/

93voto

Jay Riggs Points 30783

Voici une excellente classe qui copiera des données CSV dans une table de données en utilisant la structure des données pour créer la table de données :

Un analyseur générique portable et efficace pour les fichiers plats

Il est facile à configurer et à utiliser. Je vous invite à y jeter un coup d'œil.

0 votes

Excellent en effet. Cela a fonctionné parfaitement pour moi, sans même lire la documentation.

0 votes

Cela fonctionnera-t-il sur des fichiers CSV où chaque ligne peut avoir une structure différente ? J'ai un fichier journal avec différents types d'événements enregistrés qui doivent être séparés en plusieurs tables.

2 votes

@gonzobrains - Probablement pas ; l'hypothèse de base d'un fichier CSV est une structure de données rectangulaire basée sur un seul ensemble d'en-têtes de colonne spécifiés dans la première ligne. Ce que vous avez semble être des données discriminées, délimitées par des virgules, plus génériques, nécessitant un "ETL" plus sophistiqué pour analyser le fichier en instances d'objets de différents types (qui pourraient inclure des DataRows de différentes DataTables).

42voto

Ronnie Overby Points 11402

J'ai décidé d'utiliser Le lecteur Csv de Sébastien Lorion .

La suggestion de Jay Riggs est également une excellente solution, mais je n'avais pas besoin de toutes les fonctionnalités que cette solution. L'analyseur générique d'Andrew Rissing fournit.

UDPATE 10/25/2010

Après avoir utilisé Le lecteur Csv de Sébastien Lorion dans mon projet depuis près d'un an et demi, j'ai constaté qu'il lève des exceptions lors de l'analyse de certains fichiers csv que je pense être bien formés.

Donc, je suis passé à L'analyseur générique d'Andrew Rissing et ça semble aller beaucoup mieux.

0 votes

Je suis d'accord pour dire que le lecteur CSV de Sébastien Lorien est excellent. Je l'utilise pour les traitements CSV lourds, mais j'ai aussi utilisé celui d'Andrew Rissing pour les petits travaux et il m'a bien servi. Amusez-vous bien !

0 votes

Comment puis-je utiliser ces classes pour charger CSV dans DATATABLE ?

0 votes

J'ai essayé cela mais la collection it.Current.Keys renvoie "System.Linq.Enumerable+WhereSelectListIterator`2[System.Int32,System.Char]" au lieu du nom de la colonne. Avez-vous une idée de la raison ?

14voto

Chuck Bevitt Points 91

Nous avons toujours utilisé le pilote Jet.OLEDB, jusqu'à ce que nous commencions à utiliser des applications 64 bits. Microsoft n'a pas publié et ne publiera pas de pilote Jet 64 bits. Voici une solution simple que nous avons trouvée et qui utilise File.ReadAllLines et String.Split pour lire et analyser le fichier CSV et charger manuellement une DataTable. Comme indiqué ci-dessus, cette solution ne gère PAS la situation où l'une des valeurs de la colonne contient une virgule. Nous l'utilisons principalement pour lire des fichiers de configuration personnalisés - l'avantage d'utiliser des fichiers CSV est que nous pouvons les modifier dans Excel.

string CSVFilePathName = @"C:\test.csv";
string[] Lines = File.ReadAllLines(CSVFilePathName);
string[] Fields;
Fields = Lines[0].Split(new char[] { ',' });
int Cols = Fields.GetLength(0);
DataTable dt = new DataTable();
//1st row must be column names; force lower case to ensure matching later on.
for (int i = 0; i < Cols; i++)
    dt.Columns.Add(Fields[i].ToLower(), typeof(string));
DataRow Row;
for (int i = 1; i < Lines.GetLength(0); i++)
{
    Fields = Lines[i].Split(new char[] { ',' });
    Row = dt.NewRow();
    for (int f = 0; f < Cols; f++)
        Row[f] = Fields[f];
    dt.Rows.Add(Row);
}

8voto

Thomas Points 6809

Voici le code que j'utilise mais vos applications doivent fonctionner avec la version 3.5 du réseau.

private void txtRead_Click(object sender, EventArgs e)
        {
           // var filename = @"d:\shiptest.txt";

            openFileDialog1.InitialDirectory = "d:\\";
            openFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
            DialogResult result = openFileDialog1.ShowDialog();
            if (result == DialogResult.OK)
            {
                if (openFileDialog1.FileName != "")
                {
                    var reader = ReadAsLines(openFileDialog1.FileName);

                    var data = new DataTable();

                    //this assume the first record is filled with the column names
                    var headers = reader.First().Split(',');
                    foreach (var header in headers)
                    {
                        data.Columns.Add(header);
                    }

                    var records = reader.Skip(1);
                    foreach (var record in records)
                    {
                        data.Rows.Add(record.Split(','));
                    }

                    dgList.DataSource = data;
                }
            }
        }

        static IEnumerable<string> ReadAsLines(string filename)
        {
            using (StreamReader reader = new StreamReader(filename))
                while (!reader.EndOfStream)
                    yield return reader.ReadLine();
        }

0 votes

C'est à peu près ce que je voulais présenter.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X