【问题标题】:Write data in specific position在特定位置写入数据
【发布时间】:2021-04-22 15:50:19
【问题描述】:

我有以下代码:


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 表:

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 版本中出现问题。有什么建议吗?

【问题讨论】:

    标签: c# csvhelper


    【解决方案1】:

    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}");
    

    您将无法使用此类映射来读取您的 CSV,因为(至少从 CsvHelper 26.1.0 开始)当未映射列时读取器会抛出错误到一个类成员即使它是常量。要解决该错误,请在阅读时使用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();
        }
    }
    

    演示小提琴herehere

    【讨论】:

    • 你拯救了我的一天。这是一个不错且聪明的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-07
    • 2013-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多