【问题标题】:How to append to the same csv file with ChoETL?如何使用 ChoETL 附加到同一个 csv 文件?
【发布时间】:2020-11-12 05:41:19
【问题描述】:

目前我下面的代码调用 JsonToCsv() 来解析 JSON 文件并相应地附加到 csv,所以结果是这样的:

结果.csv

File Name    Page  Practice Name
file1.json   1     Associates & Co 

但是,如您所见,我正在使用 for 循环来迭代一堆 JSON 文件,我的目的是解析它们并将它们附加到 csv 中。所以如果我有 3 个 json 文件,预期的 csv 文件应该是这样的:

File Name    Page  Practice Name
fileXYZ.json 1     XYZ & Co
fileAB2.json 1     ABC & Co
file1.json   1     Associates & Co

但是,发生的事情是 csv 文件被覆盖,我只看到 csv 文件中最后一个文件的结果。如何让它附加到同一个文件?

static void Main(string[] args)
{
    //Output to CSV
    foreach (var jsonFile in Directory.GetFiles(jsonFilesPath))
    {
        JsonToCsv(jsonFile, csvFilePath);
    }
}

public static void JsonToCsv(string jsonInputFile, string csvFile)
{
    using (var p = new ChoJSONReader(jsonInputFile).WithJSONPath("$..readResults"))
    {
        using (var w = new ChoCSVWriter(csvFile)//.WithFirstLineHeader())
            .WithField("FileName", fieldName: "File Name")
            .WithField("Page")
            .WithField("PracticeName", fieldName: "Practice Name")
            .WithFirstLineHeader()
            )
        {
            // Limit the result to page 1 since the fields below only exist on the 1st page
            w.Write(p
                .Where(r1 => r1.page == 1)
                .Select(r1 =>
                {
                    var lines = (dynamic[])r1.lines;
                    return new
                    {
                        FileName = inputFile,
                        Page = r1.page,
                        PracticeName = lines[6].text,
                    };
                }
        ));
        }
    }
}

【问题讨论】:

  • @DCCoder 不一样。他的场景更复杂,用例也不同。他也没有在循环中使用函数。最后我确实考虑了 AppendAllText。但是,这适用于 IO 流,但我使用的是 choetl,它知道它的等价物是什么,即使这是解决方案......
  • 所以 AppendAllText 和使用 FileStream 追加不适合您的需求? (这两个都包含在该问题的答案中)。你能解释一下为什么你不能使用这两种方法吗?
  • @DCCoder 哦,我现在明白了如何用 Yegor 的回答来做到这一点。 FileMode.Append.

标签: c# choetl


【解决方案1】:

第一个选项。我建议您更改方法签名以接受多个文件。

public static void JsonToCsv(IEnumerable<string> jsonInputFiles, string csvFile)
{
    using (var w = new ChoCSVWriter(csvFile)
        .WithField("FileName", fieldName: "File Name")
        .WithField("Page")
        .WithField("PracticeName", fieldName: "Practice Name")
        .WithFirstLineHeader()
        )
    {
        foreach (var jsonInputFile in jsonInputFiles)
        {
            using (var p = new ChoJSONReader(jsonInputFile).WithJSONPath("$..readResults"))
            {
                w.Write(p
                    .Where(r1 => r1.page == 1)
                    .Select(r1 =>
                    {
                        var lines = (dynamic[])r1.lines;
                        return new
                        {
                            FileName = inputFile,
                            Page = r1.page,
                            PracticeName = lines[6].text,
                        };
                    }
                ));
            }
        }
    }
}

第二个选项。使用带有 Append 选项的 FileStream,并执行一些额外的代码来处理不同的情况,请参阅 cmets。

using (var fs = new FileStream(@"D:\file.csv", FileMode.Append, FileAccess.Write))
{
    using (var writer = new ChoCSVWriter(fs))
    {
        writer.WithField("FileName", fieldName: "File Name")
            .WithField("Page")
            .WithField("PracticeName", fieldName: "Practice Name");

        if (fs.Position == 0) // we don't need header if file already existed before
        {
            writer.WithFirstLineHeader();
        }

        writer.Write(new
        {
            FileName = "Test",
            Page = 1,
            PracticeName = "Abc"
        });

    }

    fs.Write(Environment.NewLine); // append new line carrier so we don't write to the same line when file reopened for writing
}

第三个选项 - 来自 cmets(基于第二个)。在创建和附加选项之间切换

bool someCondition = true;
FileMode fileMode = someCondition ? FileMode.Append : FileMode.Create;
using (var fs = new FileStream(@"D:\file.csv", fileMode, FileAccess.Write))

【讨论】:

  • 有趣!所以我意识到的一件事是,如果 chocsvwriter 不存在,它会很好地自动创建 csv 文件。但是,如果我想追加,就像您的选项允许的那样,但是每当启动新会话时,它会创建(覆盖)现有文件(如果有)?那将是一个不错的第三选择
  • 只需传递一个布尔标志,它将翻转 FileMode.Append 到 FileMode.Create
  • 我编辑了我的答案,请检查。 someCondition可以通过参数传递
  • 我刚刚尝试了第二个选项,效果惊人!但是,我必须在 finally 块中从 writer?.Dispose(); 中删除 ?,否则它会非常奇怪地附加。
  • 令人困惑,? 只是一个空检查。我认为它不会影响 csv 的写入
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-27
  • 2017-07-08
  • 2012-03-02
  • 2021-08-03
  • 2019-11-07
  • 2014-02-26
相关资源
最近更新 更多