所以我一直在读我不应该编写自己的CSV阅读器/写入器,所以我一直在尝试使用通过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.dll中出现“CsvHelper.Configuration.CsvConfigurationException”类型的异常,但未在用户代码中处理
附加信息:继承IEnumerable的类型无法自动映射。您是否不小心调用了对单个记录执行操作的GetRecord或WriteRecord,而不是调用作为记录列表的GetRecords或WriteRecords?
GetRecords
可能期望我自己的自定义类,但我只是想将值作为一些原始类型或字符串。此外,我怀疑整行正在转换为单个字符串,而不是每个值都是一个单独的字符串。
答案 0 :(得分:25)
根据@Marc L的帖子你可以试试这个:
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;
}
答案 1 :(得分:12)
如果您只需要数组中每行的字符串值,则可以直接使用解析器。
var parser = new CsvParser( textReader );
while( true )
{
string[] row = parser.Read();
if( row == null )
{
break;
}
}
http://joshclose.github.io/CsvHelper/#reading-parsing
<强>更新强>
版本3支持读取和编写IEnumerable属性。
答案 2 :(得分:3)
请试试这个。这对我有用。
TextReader reader = File.OpenText(filePath);
CsvReader csvFile = new CsvReader(reader);
csvFile.Configuration.HasHeaderRecord = true;
csvFile.Read();
var records = csvFile.GetRecords<Server>().ToList();
服务器是一个实体类。这就是我创造的方式。
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;
}
}
}
答案 3 :(得分:2)
你很亲密。它并不是在尝试将行转换为字符串。 CsvHelper尝试使用标题行中给出的名称将行中的每个字段映射到您为其提供的类型的属性。此外,它不了解如何使用IEnumerable
类型(string
实现)执行此操作,因此它只是在自动映射到达测试类型的那一点时抛出。
这对你正在做的事情来说是一个很大的复杂因素。如果您的文件格式足够简单,您的文件格式似乎是 - 众所周知的字段格式,既没有转义也没有引用分隔符 - 我认为没有理由需要承担导入库的开销。您应该能够根据需要使用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;
}
}
答案 4 :(得分:0)
这里的重点是读取CSV的所有行并将其反序列化为对象的集合。我不确定为什么要将它作为字符串的集合来读取。如前所述,在这种情况下,通用ReadAll()可能最适合您。当您为此目的使用该库时,它会发光:
using System.Linq;
...
using (var reader = new StreamReader(path))
using (var csv = new CsvReader(reader))
{
var yourList = csv.GetRecords<YourClass>().ToList();
}
如果您不使用ToList()-它将一次返回一条记录(以提高性能),请阅读https://joshclose.github.io/CsvHelper/examples/reading/enumerate-class-records
答案 5 :(得分:-1)
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();
}