读取CSV文件并将值存储到数组中
我正在尝试读取*.csv
文件。
*.csv
文件由用分号(“ ; ”)分隔的两列组成。
我能够使用StreamReader读取*.csv
文件,并能够使用Split()
函数分隔每一行。 我想将每列存储到一个单独的数组,然后显示它。
有没有可能做到这一点?
你可以这样做:
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]); } } }
LINQ方式:
var lines = File.ReadAllLines("test.txt").Select(a => a.Split(';')); var csv = from line in lines select (from piece in line select piece);
^^错误 – 由Nick编辑
看起来原来的回答者正试图用一个二维数组(包含数组的数组)填充csv
。 第一个数组中的每个项目都包含一个表示该行号的数组,每个嵌套数组中的每个项目都包含该特定列的数据。
var csv = from line in lines select (line.Split(',')).ToArray();
我最喜欢的csv解析器是一个内置的.net库。 这是Microsoft.VisualBasic命名空间内的一个隐藏的宝藏。 以下是一个示例代码:
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]; } }
有关解析器的更多细节在这里给出: http : //codeskaters.blogspot.ae/2015/11/c-easiest-csv-parser-built-in-net.html
我通常在codeproject中使用这个解析器 ,因为有一堆字符转义和它为我处理的类似。
这是我顶尖投票答案的变化:
var contents = File.ReadAllText(filename).Split('\n'); var csv = from line in contents select line.Split(',').ToArray();
然后可以使用csv
变量,如下例所示:
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]; }
你不能立即创建一个数组,因为你需要知道从一开始的行数(这将需要读取两次csv文件)
您可以将值存储在两个List<T>
,然后使用它们或使用List<T>.ToArray()
将其转换为数组。
很简单的例子:
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);
刚刚遇到这个库: https : //github.com/JoshClose/CsvHelper
非常直观,易于使用。 也有一个nuget包,这使得快速实现: http ://nuget.org/packages/CsvHelper/1.17.0。 也似乎积极维护,我喜欢。
配置它使用分号很容易: https : //github.com/JoshClose/CsvHelper/wiki/Custom-Configurations
如果您需要跳过(head-)行和/或列,可以使用它来创建一个二维数组:
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
如果在进一步处理数据之前需要对数据进行整形(假设前两行由标题组成,第一列是行标题,那么这在数组中是不需要的)要把数据)。
注意您可以使用以下代码轻松获得标题和第一列:
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
此代码示例假定您的*.csv
文件的以下结构:
注意:如果您需要跳过空行(有时可以方便的话),您可以通过插入来完成
where line.Any(a=>!string.IsNullOrWhiteSpace(a))
在上面的LINQ代码示例中的from
和select
语句之间。
您可以在C#中使用Microsoft.VisualBasic.FileIO.TextFieldParser DLL以获得更好的性能
从上面的文章得到下面的代码示例
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; }
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();
开源的Angara.Table库允许将CSV加载到类型列中,以便从列中获取数组。 每列可以通过名称或索引进行索引。 请参阅http://predictionmachines.github.io/Angara.Table/saveload.html 。
该库遵循RFC4180的CSV; 它启用类型推断和多行字符串。
例:
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]); }
您可以使用Column类型来查看列类型,例如
Column c = table["double-column-name"]; Console.WriteLine("Column {0} is double: {1}", c.Name, c.Rows.IsRealColumn);
由于该库专注于F#,因此可能需要添加对FSharp.Core 4.4程序集的引用; 单击该项目上的“添加引用”,然后选择“Assemblies” – >“Extensions”下的FSharp.Core 4.4。
在这种情况下,其中一个数据字段具有分号(“;”)作为其数据的一部分,在这种情况下,大多数答案都会失败。
解决它的情况将是
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(); }
我一直在使用csvreader.com(付费组件)多年,我从来没有遇到过问题。 这是坚实的,小而快的,但你必须付出代价。 您可以将分隔符设置为任何你喜欢的。
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] ... }
我有一个正在做你需要的图书馆。
前一段时间我写了简单而快速的库来处理CSV文件。 你可以通过以下链接找到它: https : //github.com/ukushu/DataExporter
我的工作与CSV像2维数组。 完全像你需要的。
例如,如果您需要第三行的所有值,则只需要编写以下内容:
Csv csv = new Csv(); csv.FileOpen("c:\\file1.csv"); var allValuesOf3rdRow = csv.Rows[2];
或阅读第二个单元格
var value = csv.Rows[2][1];
我只是学生在做我的硕士论文,但这是我解决这个问题的方法,对我来说也很好。 首先你从目录中选择你的文件(只用csv格式),然后把数据放到列表中。
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 ); } }
大家好,我创建了一个静态类来做到这一点。 +列检查+配额标志删除
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; } }
还是错的。 你需要用引号补偿“”。 这是我的解决方案微软风格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; } }