使用 CsvHelper 将 CSV 中的所有值读入列表
Read all values from CSV into a List using CsvHelper
所以我一直在读到我不应该编写自己的 CSV reader/writer,所以我一直在尝试使用通过 nuget 安装的 CsvHelper 库。 CSV 文件是灰度图像,行数为图像高度,列数为宽度。我想将值逐行读入单个 List<string>
或 List<byte>
.
我目前的代码是:
using CsvHelper;
public static List<string> ReadInCSV(string absolutePath)
{
IEnumerable<string> allValues;
using (TextReader fileReader = File.OpenText(absolutePath))
{
var csv = new CsvReader(fileReader);
csv.Configuration.HasHeaderRecord = false;
allValues = csv.GetRecords<string>
}
return allValues.ToList<string>();
}
但是 allValues.ToList<string>()
正在抛出一个:
用户代码未处理 CsvConfigurationException
类型'CsvHelper.Configuration.CsvConfigurationException'的异常发生在CsvHelper.dll,但未在用户代码中处理
附加信息:无法自动映射继承 IEnumerable 的类型。您是否不小心调用了作用于单个记录的 GetRecord 或 WriteRecord,而不是调用了作用于记录列表的 GetRecords 或 WriteRecords?
GetRecords
可能需要我自己的自定义 class,但我只是希望这些值是某种原始类型或字符串。另外,我怀疑整行都被转换为一个字符串,而不是每个值都是一个单独的字符串。
你很接近。这并不是说它试图将 行 转换为字符串。 CsvHelper 尝试使用 header 行中给定的名称将行中的每个字段映射到您为其指定的类型的属性。此外,它不明白如何使用 IEnumerable
类型(string
实现)来执行此操作,因此它只是在 auto-mapping 达到测试类型的那个点时抛出。
对于您正在做的事情来说,这太复杂了。如果您的文件格式足够简单,您的文件格式似乎是——众所周知的字段格式,既没有转义分隔符也没有引号分隔符——我认为您没有理由需要承担导入库的开销。您应该能够根据需要使用 System.IO.File.ReadLines()
和 String.Split()
.
枚举值
//pseudo-code...you don't need CsvHelper for this
IEnumerable<string> GetFields(string filepath)
{
foreach(string row in File.ReadLines(filepath))
{
foreach(string field in row.Split(',')) yield return field;
}
}
根据@Marc L 的 post 你可以试试这个:
public static List<string> ReadInCSV(string absolutePath) {
List<string> result = new List<string>();
string value;
using (TextReader fileReader = File.OpenText(absolutePath)) {
var csv = new CsvReader(fileReader);
csv.Configuration.HasHeaderRecord = false;
while (csv.Read()) {
for(int i=0; csv.TryGetField<string>(i, out value); i++) {
result.Add(value);
}
}
}
return result;
}
如果您只需要数组中每一行的字符串值,您可以直接使用解析器。
var parser = new CsvParser( textReader );
while( true )
{
string[] row = parser.Read();
if( row == null )
{
break;
}
}
http://joshclose.github.io/CsvHelper/#reading-parsing
更新
版本 3 支持读取和写入 IEnumerable
属性。
请试试这个。这对我有用。
TextReader reader = File.OpenText(filePath);
CsvReader csvFile = new CsvReader(reader);
csvFile.Configuration.HasHeaderRecord = true;
csvFile.Read();
var records = csvFile.GetRecords<Server>().ToList();
服务器是一个实体class。我就是这样创建的。
public class Server
{
private string details_Table0_ProductName;
public string Details_Table0_ProductName
{
get
{
return details_Table0_ProductName;
}
set
{
this.details_Table0_ProductName = value;
}
}
private string details_Table0_Version;
public string Details_Table0_Version
{
get
{
return details_Table0_Version;
}
set
{
this.details_Table0_Version = value;
}
}
}
这里的重点是读取 CSV 的所有行并将其反序列化为对象集合。我不确定您为什么要将其作为字符串集合来阅读。如前所述,在这种情况下,通用 ReadAll()
可能最适合您。当您将它用于此目的时,这个库会大放异彩:
using System.Linq;
...
using (var reader = new StreamReader(path))
using (var csv = new CsvReader(reader))
{
var yourList = csv.GetRecords<YourClass>().ToList();
}
如果您不使用 ToList()
- 它会 return 一次一条记录(为了更好的性能),请阅读 https://joshclose.github.io/CsvHelper/examples/reading/enumerate-class-records
static void WriteCsvFile(string filename, IEnumerable<Person> people)
{
StreamWriter textWriter = File.CreateText(filename);
var csvWriter = new CsvWriter(textWriter, System.Globalization.CultureInfo.CurrentCulture);
csvWriter.WriteRecords(people);
textWriter.Close();
}
所以我一直在读到我不应该编写自己的 CSV reader/writer,所以我一直在尝试使用通过 nuget 安装的 CsvHelper 库。 CSV 文件是灰度图像,行数为图像高度,列数为宽度。我想将值逐行读入单个 List<string>
或 List<byte>
.
我目前的代码是:
using CsvHelper;
public static List<string> ReadInCSV(string absolutePath)
{
IEnumerable<string> allValues;
using (TextReader fileReader = File.OpenText(absolutePath))
{
var csv = new CsvReader(fileReader);
csv.Configuration.HasHeaderRecord = false;
allValues = csv.GetRecords<string>
}
return allValues.ToList<string>();
}
但是 allValues.ToList<string>()
正在抛出一个:
用户代码未处理 CsvConfigurationException
类型'CsvHelper.Configuration.CsvConfigurationException'的异常发生在CsvHelper.dll,但未在用户代码中处理
附加信息:无法自动映射继承 IEnumerable 的类型。您是否不小心调用了作用于单个记录的 GetRecord 或 WriteRecord,而不是调用了作用于记录列表的 GetRecords 或 WriteRecords?
GetRecords
可能需要我自己的自定义 class,但我只是希望这些值是某种原始类型或字符串。另外,我怀疑整行都被转换为一个字符串,而不是每个值都是一个单独的字符串。
你很接近。这并不是说它试图将 行 转换为字符串。 CsvHelper 尝试使用 header 行中给定的名称将行中的每个字段映射到您为其指定的类型的属性。此外,它不明白如何使用 IEnumerable
类型(string
实现)来执行此操作,因此它只是在 auto-mapping 达到测试类型的那个点时抛出。
对于您正在做的事情来说,这太复杂了。如果您的文件格式足够简单,您的文件格式似乎是——众所周知的字段格式,既没有转义分隔符也没有引号分隔符——我认为您没有理由需要承担导入库的开销。您应该能够根据需要使用 System.IO.File.ReadLines()
和 String.Split()
.
//pseudo-code...you don't need CsvHelper for this
IEnumerable<string> GetFields(string filepath)
{
foreach(string row in File.ReadLines(filepath))
{
foreach(string field in row.Split(',')) yield return field;
}
}
根据@Marc L 的 post 你可以试试这个:
public static List<string> ReadInCSV(string absolutePath) {
List<string> result = new List<string>();
string value;
using (TextReader fileReader = File.OpenText(absolutePath)) {
var csv = new CsvReader(fileReader);
csv.Configuration.HasHeaderRecord = false;
while (csv.Read()) {
for(int i=0; csv.TryGetField<string>(i, out value); i++) {
result.Add(value);
}
}
}
return result;
}
如果您只需要数组中每一行的字符串值,您可以直接使用解析器。
var parser = new CsvParser( textReader );
while( true )
{
string[] row = parser.Read();
if( row == null )
{
break;
}
}
http://joshclose.github.io/CsvHelper/#reading-parsing
更新
版本 3 支持读取和写入 IEnumerable
属性。
请试试这个。这对我有用。
TextReader reader = File.OpenText(filePath);
CsvReader csvFile = new CsvReader(reader);
csvFile.Configuration.HasHeaderRecord = true;
csvFile.Read();
var records = csvFile.GetRecords<Server>().ToList();
服务器是一个实体class。我就是这样创建的。
public class Server
{
private string details_Table0_ProductName;
public string Details_Table0_ProductName
{
get
{
return details_Table0_ProductName;
}
set
{
this.details_Table0_ProductName = value;
}
}
private string details_Table0_Version;
public string Details_Table0_Version
{
get
{
return details_Table0_Version;
}
set
{
this.details_Table0_Version = value;
}
}
}
这里的重点是读取 CSV 的所有行并将其反序列化为对象集合。我不确定您为什么要将其作为字符串集合来阅读。如前所述,在这种情况下,通用 ReadAll()
可能最适合您。当您将它用于此目的时,这个库会大放异彩:
using System.Linq;
...
using (var reader = new StreamReader(path))
using (var csv = new CsvReader(reader))
{
var yourList = csv.GetRecords<YourClass>().ToList();
}
如果您不使用 ToList()
- 它会 return 一次一条记录(为了更好的性能),请阅读 https://joshclose.github.io/CsvHelper/examples/reading/enumerate-class-records
static void WriteCsvFile(string filename, IEnumerable<Person> people)
{
StreamWriter textWriter = File.CreateText(filename);
var csvWriter = new CsvWriter(textWriter, System.Globalization.CultureInfo.CurrentCulture);
csvWriter.WriteRecords(people);
textWriter.Close();
}