J'essaie de lire un fichier *.csv
-.
Le fichier *.csv
- est composé de deux colonnes séparées par un point-virgule ("; ").
Je peux lire le fichier *.csv
- à l'aide de StreamReader et séparer chaque ligne à l'aide de la fonction Split()
. Je veux stocker chaque colonne dans un tableau séparé, puis l'afficher.
Est-il possible de faire ça?
Vous pouvez le faire comme ça:
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]);
}
}
}
Mon analyseur CSV préféré est celui intégré à la bibliothèque .net. Il s'agit d'un trésor caché à l'intérieur de l'espace de noms Microsoft.VisualBasic . Vous trouverez ci-dessous un exemple de code:
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];
}
}
N'oubliez pas d'ajouter une référence à Microsoft.VisualBasic
Plus de détails sur l'analyseur sont donnés ici: http://codeskaters.blogspot.ae/2015/11/c-easiest-csv-parser-built-in-net.html
Façon LINQ:
var lines = File.ReadAllLines("test.txt").Select(a => a.Split(';'));
var csv = from line in lines
select (from piece in line
select piece);
^^ Wrong - Edit by Nick
Il semble que le répondant d'origine tentait de peupler csv
avec un tableau à 2 dimensions - un tableau contenant des tableaux. Chaque élément du premier tableau contient un tableau représentant ce numéro de ligne, chaque élément du tableau imbriqué contenant les données de cette colonne spécifique.
var csv = from line in lines
select (line.Split(',')).ToArray();
J'utilise habituellement cet analyseur de codeproject , car il y a un tas d'échappements de caractères et similaires qu'il gère pour moi.
Voici ma variante de la réponse la plus votée:
var contents = File.ReadAllText(filename).Split('\n');
var csv = from line in contents
select line.Split(',').ToArray();
La variable csv
peut ensuite être utilisée comme dans l'exemple suivant:
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];
}
Je viens de trouver cette bibliothèque: https://github.com/JoshClose/CsvHelper
Très intuitif et facile à utiliser. A aussi un paquet de nuget qui est rapide à mettre en œuvre: http://nuget.org/packages/CsvHelper/1.17.0 . Semble également être activement maintenu que j'aime bien.
La configuration pour utiliser un point-virgule est simple: https://github.com/JoshClose/CsvHelper/wiki/Custom-Configurations
Vous ne pouvez pas créer un tableau immédiatement car vous devez connaître le nombre de lignes depuis le début (et cela nécessiterait de lire le fichier csv deux fois).
Vous pouvez stocker des valeurs dans deux List<T>
puis les utiliser ou les convertir en tableau à l’aide de List<T>.ToArray()
.
Exemple très simple:
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.
S'il vous plaît noter que ceci est juste un exemple très simple . L'utilisation de string.Split
ne prend pas en compte les cas où certains enregistrements contiennent le séparateur ;
à l'intérieur.
Pour une approche plus sûre, envisagez l’utilisation de bibliothèques spécifiques à csv, telles que CsvHelper sur nuget.
Si vous devez sauter des lignes et/ou des colonnes (en-tête), vous pouvez utiliser ceci pour créer un tableau à 2 dimensions:
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
Ceci est très utile si vous avez besoin de façonner les données avant de les traiter davantage (en supposant que les 2 premières lignes sont constituées du titre et que la première colonne est un titre de ligne - que vous n’avez pas besoin d’avoir dans le tableau vouloir regarder les données).
N.B. Vous pouvez facilement obtenir les titres et la 1ère colonne en utilisant le code suivant:
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
Cet exemple de code suppose la structure suivante de votre fichier *.csv
:
Remarque: Si vous devez ignorer les lignes vides - ce qui peut parfois être pratique, vous pouvez le faire en insérant
where line.Any(a=>!string.IsNullOrWhiteSpace(a))
entre les instructions from
et select
dans les exemples de codeLINQci-dessus.
Vous pouvez utiliser Microsoft.VisualBasic.FileIO.TextFieldParser dll en C # pour de meilleures performances.
obtenir ci-dessous exemple de code de l'article ci-dessus
static void Main()
{
string csv_file_path=@"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;
}
Bonjour à tous, j’ai créé une classe statique pour ce faire . + Vérification des colonnes + Suppression du signe de quota
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;
}
}
Voici un cas particulier où l'un des champs de données comporte un point-virgule (";") dans ses données. Dans ce cas, la plupart des réponses ci-dessus échoueront.
Solution ce cas sera
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();
}
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();
La bibliothèque open-source Angara.Table permet de charger des fichiers CSV dans des colonnes typées afin que vous puissiez obtenir les tableaux à partir des colonnes. Chaque colonne peut être indexée à la fois par nom ou par index. Voir http://predictionmachines.github.io/Angara.Table/saveload.html .
La bibliothèque suit RFC4180 pour CSV; il permet l'inférence de type et les chaînes multilignes.
Exemple:
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]);
}
Vous pouvez voir un type de colonne en utilisant le type Column, par exemple.
Column c = table["double-column-name"];
Console.WriteLine("Column {0} is double: {1}", c.Name, c.Rows.IsRealColumn);
Comme la bibliothèque est concentrée sur F #, vous devrez peut-être ajouter une référence à FSharp.Core 4.4 Assembly; Cliquez sur "Ajouter une référence" dans le projet et choisissez FSharp.Core 4.4 sous "Assemblies" -> "Extensions".
Je suis juste un étudiant en train de travailler sur ma thèse de maîtrise, mais c'est ainsi que je l'ai résolue et cela a bien fonctionné pour moi. Tout d’abord, vous sélectionnez votre fichier à partir du répertoire (uniquement au format csv), puis vous placez les données dans les listes.
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
);
}
}
J'utilise csvreader.com (composant payant) depuis des années et je n'ai jamais eu de problème. Il est solide, petit et rapide, mais vous devez le payer. Vous pouvez définir le délimiteur à votre guise.
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] ...
}
Toujours incorrecte. Vous devez compenser "" entre guillemets . Voici ma solution style Microsoft 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;
}
}
J'ai passé quelques heures à chercher une bonne bibliothèque, mais j'ai finalement écrit mon propre code :) Vous pouvez lire le fichier (ou la base de données) avec tous les outils de votre choix, puis appliquer la routine suivante à chaque ligne:
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();
}
J'ai une bibliothèque qui fait exactement ce dont vous avez besoin.
Il y a quelque temps, j'avais écrit une bibliothèque assez simple et rapide pour travailler avec des fichiers CSV. Vous pouvez le trouver en cliquant sur le lien suivant: https://github.com/ukushu/DataExporter
Cela fonctionne avec CSV comme avec le tableau à 2 dimensions. Exactement comme vous en avez besoin.
Par exemple, si vous avez besoin de toutes les valeurs de la 3ème ligne, il vous suffit d'écrire:
Csv csv = new Csv();
csv.FileOpen("c:\\file1.csv");
var allValuesOf3rdRow = csv.Rows[2];
ou lire la 2e cellule de
var value = csv.Rows[2][1];