CsvHelper - 在同一CSV中读取不同的记录类型 [英] CsvHelper - Read different record types in same CSV
问题描述
我尝试从以下结构的CSV文件中读取两种类型的记录:
I'm trying to read two types of records out of a CSV file with the following structure:
PlaceName,Longitude,Latitude,Elevation
NameString,123.456,56.78,40
Date,Count
1/1/2012,1
2/1/2012,3
3/1/2012,10
4/2/2012,6
我知道这个问题已经在
- Reading multiple classes from single csv file using CsvHelper
- Multiple Record Types in One File?
但是当我运行我的实现它得到一个 CsvMissingFieldException
说,字段'日期'不存在于CSV文件
。我有两个定义和映射类,一个用于位置,另一个用于计数,它们是:
but when I run my implementation it gets a CsvMissingFieldException
saying that Fields 'Date' do not exist in the CSV file
. I have two definition and map classes, one for the location and the other for the counts, which are:
public class LocationDefinition
{
public string PlaceName { get; set; }
public double Longitude { get; set; }
public double Latitude { get; set; }
public double Elevation { get; set; }
}
public sealed class LocationMap : CsvClassMap<LocationDefinition>
{
public LocationMap()
{
Map(m => m.PlaceName).Name("PlaceName");
Map(m => m.Longitude).Name("Longitude");
Map(m => m.Latitude).Name("Latitude");
Map(m => m.Elevation).Name("Elevation");
}
}
public class CountDefinition
{
public DateTime Date { get; set; }
public int Count { get; set; }
}
public sealed class CountMap : CsvClassMap<CountDefinition>
{
public CountMap()
{
Map(m => m.Date).Name("Date");
Map(m => m.Count).Name("Count");
}
}
我读取csv文件的代码是:
The code that I have for reading the csv file is:
LocationDefinition Location;
var Counts = new List<CountDefinition>();
using (TextReader fileReader = File.OpenText(@"Path\To\CsvFile"))
using (var csvReader = new CsvReader(fileReader))
{
csvReader.Configuration.RegisterClassMap<LocationMap>();
csvReader.Configuration.RegisterClassMap<CountMap>();
// Only reads a single line of Location data
csvReader.Read();
LocationData = csvReader.GetRecord<LocationDefinition>();
csvReader.Read(); // skip blank line
csvReader.Read(); // skip second header section
// Read count data records
while (csvReader.Read())
{
var tempCount = csvReader.GetRecord<CountDefinition>();
Counts.Add(tempCount);
}
}
异常被抛出 tempCount
行。从我可以告诉它仍然期望一个位置记录,但我会认为 GetRecord< CountDefinition>
将指定记录类型。我也尝试过 ClearRecordCache
,取消注册 LocationMap
无效。
The exception gets thrown on the tempCount
line. From what I can tell it still expects a Location record, but I would have thought GetRecord<CountDefinition>
would specify the record type. I've also tried ClearRecordCache
and unregistering the LocationMap
to no avail.
如何改变这个代码来读取这个结构的csv文件?
How should this code be changed to get it to read a csv file of this structure?
推荐答案
来自Josh Close对问题跟踪器的回复:
I got a response from Josh Close on the issue tracker:
这是他对此问题的回答:
Here is his answer to this question:
因为你没有一个头,你需要忽略头文件
并改用索引。这产生了一个想法。我可以有
ReadHeader方法解析特定记录类型的头文件。
Since you don't have a single header, you'll need to ignore headers and use indexes instead. This brings up an idea though. I could have the ReadHeader method parse headers for a specific record type.
这里是一个应该为你工作的例子。
Here is an example that should work for you though.
void Main()
{
LocationDefinition Location;
var Counts = new List<CountDefinition>();
using (var stream = new MemoryStream())
using (var reader = new StreamReader(stream))
using (var writer = new StreamWriter(stream))
using (var csvReader = new CsvReader(reader))
{
writer.WriteLine("PlaceName,Longitude,Latitude,Elevation");
writer.WriteLine("NameString,123.456,56.78,40");
writer.WriteLine();
writer.WriteLine("Date,Count");
writer.WriteLine("1/1/2012,1");
writer.WriteLine("2/1/2012,3");
writer.WriteLine("3/1/2012,10");
writer.WriteLine("4/2/2012,6");
writer.Flush();
stream.Position = 0;
csvReader.Configuration.HasHeaderRecord = false;
csvReader.Configuration.RegisterClassMap<LocationMap>();
csvReader.Configuration.RegisterClassMap<CountMap>();
csvReader.Read(); // get header
csvReader.Read(); // get first record
var locationData = csvReader.GetRecord<LocationDefinition>();
csvReader.Read(); // skip blank line
csvReader.Read(); // skip second header section
// Read count data records
while (csvReader.Read())
{
var tempCount = csvReader.GetRecord<CountDefinition>();
Counts.Add(tempCount);
}
}
}
public class LocationDefinition
{
public string PlaceName { get; set; }
public double Longitude { get; set; }
public double Latitude { get; set; }
public double Elevation { get; set; }
}
public sealed class LocationMap : CsvClassMap<LocationDefinition>
{
public LocationMap()
{
Map(m => m.PlaceName);
Map(m => m.Longitude);
Map(m => m.Latitude);
Map(m => m.Elevation);
}
}
public class CountDefinition
{
public DateTime Date { get; set; }
public int Count { get; set; }
}
public sealed class CountMap : CsvClassMap<CountDefinition>
{
public CountMap()
{
Map(m => m.Date);
Map(m => m.Count);
}
}
这篇关于CsvHelper - 在同一CSV中读取不同的记录类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!