【问题标题】:Modify CSV file headers/column names using Cinchoo ETL使用 Cinchoo ETL 修改 CSV 文件标题/列名
【发布时间】:2018-12-14 13:42:49
【问题描述】:

我有一个 .Net Core 应用程序,我想在其中更改 csv 文件的列名。我正在使用 Cinchoo ETL 库。我尝试了以下方法:

string csv = "../../../../data.csv";
using (var w = new ChoCSVWriter(csv).WithFirstLineHeader().Setup(s => s.FileHeaderWrite += (o, e) =>
{
    e.HeaderText = "Test,Test2";
}))
{
    w.Write(csv);
}

这就是我的 data.csv 文件的样子:

ID,Name
1, David
2, Bob

这是我的 csv 在运行我的代码后的样子:

Test,Test2
../../../../data.csv

csv 标头名称已更改,但我的问题是它删除了我的所有数据并出于某种奇怪的原因添加了文件的路径。关于为什么会这样的任何想法?

【问题讨论】:

  • w.Write(csv); 应该具有此功能
  • 谢谢!你有什么图书馆吗?我使用这个库的原因是因为我还需要将 csv 转换为 json
  • 我过去使用过CsvHelper,效果很好。至于 JSON 部分,如果你使用强类型模型,你可以很容易地使用 NewtonsoftJSON 在 libs 之间来回转换。
  • 您也可以使用dynamic 或匿名类型,但从长远来看,我更喜欢类型安全作为个人偏好。如果您使用的是 .NET 核心,则已包含 JSON 支持。目前他们使用 Newtonsoft。
  • 这是一个基本的gist

标签: c# .net .net-core choetl


【解决方案1】:

用新名称重命名列并生成 CSV 输出的几种方法

选项1:

StringBuilder csvIn = new StringBuilder(@"ID,Name
1, David
2, Bob");

StringBuilder csvOut = new StringBuilder();

using (var r = new ChoCSVReader(csvIn)
    .WithFirstLineHeader()
    )
{
    using (var w = new ChoCSVWriter(csvOut)
        .WithFirstLineHeader()
        )
        w.Write(r.Select(r1 => new { Test1 = r1.ID, Test2 = r1.Name }));
}

Console.WriteLine(csvOut.ToString());

选项2:

StringBuilder csvIn = new StringBuilder(@"ID,Name
1, David
2, Bob");

StringBuilder csvOut = new StringBuilder();

using (var r = new ChoCSVReader(csvIn)
    .WithFirstLineHeader()
    )
{
    using (var w = new ChoCSVWriter(csvOut)
        .WithFirstLineHeader()
        .Setup(s => s.FileHeaderWrite += (o, e) =>
        {
            e.HeaderText = "Test,Test2";
        })
        )
        w.Write(r);
}

Console.WriteLine(csvOut.ToString());

更新:

使用 CSV 文件代替文本输入

string csvInFilePath = @"C:\CSVIn.csv"
string csvOutFilePath = @"C:\CSVOut.csv"

using (var r = new ChoCSVReader(csvInFilePath)
    .WithFirstLineHeader()
    )
{
    using (var w = new ChoCSVWriter(csvOutFilePath)
        .WithFirstLineHeader()
        )
        w.Write(r.Select(r1 => new { Test1 = r1.ID, Test2 = r1.Name }));
}

更新:

要获取标题,请将记录转换为 IDictionary 并在其上使用 Keys 属性来获取键

string csvInFilePath = @"C:\CSVIn.csv"
string csvOutFilePath = @"C:\CSVOut.csv"

using (var r = new ChoCSVReader(csvInFilePath)
    .WithFirstLineHeader()
    )
{
    foreach (IDictionary<string, object> rec in r)
    {
         var keys = rec.Keys.ToArray();
    }
}

为了自动发现 CSV 列的数据类型,您必须在解析器上设置 MaxScanRows。否则所有列都将被视为字符串类型。

StringBuilder csvIn = new StringBuilder(@"ID,Name,Date
1, David, 1/1/2018
2, Bob, 2/12/2019");

using (var r = new ChoCSVReader(csvIn)
    .WithFirstLineHeader()
    .WithMaxScanRows(2)
    )
{
    foreach (IDictionary<string, object> rec in r.Take(1))
    {
        foreach (var kvp in rec)
            Console.WriteLine($"{kvp.Key} - {r.Configuration[kvp.Key].FieldType}");
    }
}

希望对你有帮助。

【讨论】:

  • 感谢您的回答!如何传递一个 csv 文件路径而不是 (@"ID,Name 1, David 2, Bob");
  • 将 CSV 文件路径(入站/出站)传递给构造函数。
  • 这对我来说很好用。我更改了列名,然后将所有内容都转换为 json。我是否对 StringBuilders 重复了太多?有没有办法优化它? gist.github.com/sbattoh/6d5531c2e6c2841ac48175a37b0ebf2f
  • 你的要求很简单。使用新的字段名称将 CSV 转换为 JSON。非常简单。请参阅 gist 中的更新。
  • 嗨,如何获取标头及其类型的列表?
猜你喜欢
  • 2021-07-20
  • 1970-01-01
  • 2014-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-05
  • 1970-01-01
  • 2016-01-05
相关资源
最近更新 更多