在特定位置写入数据
Write data in specific position
我有以下代码:
class Dto
{
public string Data1 { get; set; }
public string DataN { get; set; }
public string DataN1 { get; set; }
}
class DtoMap : ClassMap<Dto>
{
public DtoMap()
{
Map(x => x.Data1).Index(0);
// Note that I need to skip N columns
Map(x => x.DataN).Index(N);
Map(x => x.DataN1).Index(N1);
}
}
// create csv
using (var memoryStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memoryStream))
using (var csvWriter = new CsvWriter(streamWriter, csvConfiguration))
{
csvWriter.Configuration.RegisterClassMap<TMap>();
csvWriter.WriteRecords(records);
streamWriter.Flush();
return memoryStream.ToArray();
}
预期结果为以下 CSV table:
header 1
header ...
header n
header n + 1
Data 1
...
Data N
Data N + 1
Data 2
...
Data N
Data N + 1
似乎在写入 csv 文件时忽略了索引。问题发生在 15.0.6 和 26.0.0 版本。有什么建议吗?
CsvHelper 将按照索引指定的顺序输出列,但不会为缺少的索引添加空列。如果您需要这样做,您可以使用 Map().Index(i).Constant("");
来指示应在特定索引 i
处使用常量值。使用它为要留空的列填充常量空值:
class DtoMap : ClassMap<Dto>
{
const int N = 12;
public DtoMap() : this(true) { }
public DtoMap(bool includeEmptyColumns)
{
Map(x => x.Data1).Index(0);
if (includeEmptyColumns)
{
for (int i = 1; i < N; i++)
{
Map().Index(i).Constant("");
}
}
// Note that I need to skip N columns
Map(x => x.DataN).Index(N);
Map(x => x.DataN1).Index(N + 1);
}
}
参见:Constant Value。
这会使列标题留空。如果您需要提供一些默认列标题,您可以使用 .Name(string)
:
指定一个
Map().Index(i).Constant("").Name($"Column {i}");
您将无法使用此 class 映射到 读取 您的 CSV,但是,因为(至少从 CsvHelper 26.1.0 开始)[=当列未映射到 class 成员 时,37=] 将抛出错误,即使它是常量 。要解决该错误,请在阅读时使用 new DtoMap(false)
,即:
var newRecords = ReadCSV(csv, new DtoMap(false), config);
static List<TRecords> ReadCSV<TRecords>(byte [] data, ClassMap<TRecords> map, CsvConfiguration csvConfiguration)
{
using (var memoryStream = new MemoryStream(data))
using (var streamWriter = new StreamReader(memoryStream))
using (var csvReader = new CsvReader(streamWriter, csvConfiguration))
{
csvReader.Context.RegisterClassMap(map);
return csvReader.GetRecords<TRecords>().ToList();
}
}
我有以下代码:
class Dto
{
public string Data1 { get; set; }
public string DataN { get; set; }
public string DataN1 { get; set; }
}
class DtoMap : ClassMap<Dto>
{
public DtoMap()
{
Map(x => x.Data1).Index(0);
// Note that I need to skip N columns
Map(x => x.DataN).Index(N);
Map(x => x.DataN1).Index(N1);
}
}
// create csv
using (var memoryStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memoryStream))
using (var csvWriter = new CsvWriter(streamWriter, csvConfiguration))
{
csvWriter.Configuration.RegisterClassMap<TMap>();
csvWriter.WriteRecords(records);
streamWriter.Flush();
return memoryStream.ToArray();
}
预期结果为以下 CSV table:
header 1 | header ... | header n | header n + 1 |
---|---|---|---|
Data 1 | ... | Data N | Data N + 1 |
Data 2 | ... | Data N | Data N + 1 |
似乎在写入 csv 文件时忽略了索引。问题发生在 15.0.6 和 26.0.0 版本。有什么建议吗?
CsvHelper 将按照索引指定的顺序输出列,但不会为缺少的索引添加空列。如果您需要这样做,您可以使用 Map().Index(i).Constant("");
来指示应在特定索引 i
处使用常量值。使用它为要留空的列填充常量空值:
class DtoMap : ClassMap<Dto>
{
const int N = 12;
public DtoMap() : this(true) { }
public DtoMap(bool includeEmptyColumns)
{
Map(x => x.Data1).Index(0);
if (includeEmptyColumns)
{
for (int i = 1; i < N; i++)
{
Map().Index(i).Constant("");
}
}
// Note that I need to skip N columns
Map(x => x.DataN).Index(N);
Map(x => x.DataN1).Index(N + 1);
}
}
参见:Constant Value。
这会使列标题留空。如果您需要提供一些默认列标题,您可以使用 .Name(string)
:
Map().Index(i).Constant("").Name($"Column {i}");
您将无法使用此 class 映射到 读取 您的 CSV,但是,因为(至少从 CsvHelper 26.1.0 开始)[=当列未映射到 class 成员 时,37=] 将抛出错误,即使它是常量 。要解决该错误,请在阅读时使用 new DtoMap(false)
,即:
var newRecords = ReadCSV(csv, new DtoMap(false), config);
static List<TRecords> ReadCSV<TRecords>(byte [] data, ClassMap<TRecords> map, CsvConfiguration csvConfiguration)
{
using (var memoryStream = new MemoryStream(data))
using (var streamWriter = new StreamReader(memoryStream))
using (var csvReader = new CsvReader(streamWriter, csvConfiguration))
{
csvReader.Context.RegisterClassMap(map);
return csvReader.GetRecords<TRecords>().ToList();
}
}