【问题标题】:Quickly replace first line of large file快速替换大文件的第一行
【发布时间】:2012-11-24 18:10:46
【问题描述】:

我有许多大型 csv 文件(每个 1-10 gb)要导入数据库。对于每个文件,我需要替换第一行,以便将标题格式化为列名。我目前的解决方案是:

using (var reader = new StreamReader(file))
{
    using (var writer = new StreamWriter(fixed))
    {
        var line = reader.ReadLine();
        var fixedLine = parseHeaders(line);
        writer.WriteLine(fixedLine);

        while ((line = reader.ReadLine()) != null)
            writer.WriteLine(line);
    }
}

什么是只替换第 1 行而不遍历这些大文件的每一行的更快方法?

【问题讨论】:

  • 我可能只是从命令行执行此操作。 copy headerfile+csvfile newfile 您可以制作一个包含所有需要更改的文件的批处理文件。 (哦,除了看起来你事先不知道标题是什么。如果不知道,这将无济于事。)
  • 如果您使用的工具碰巧通过stdin 接受输入:而不是文件,您可以创建一个由标题和正文组成的流,并在您输入时将其输入您的导入工具需要它。例如cat headerfile bigfile | import_tool
  • 这对fixedLine和第一行的Lengths非常敏感。固定线可以更大吗? line2 可以移动到文件末尾吗?

标签: c# replace


【解决方案1】:

如果您可以保证fixedLineline 的长度相同(或更少),您可以就地更新文件而不是复制它们。

如果没有,您可以通过访问 StreamReaderStreamWriter.BaseStream 并执行大块复制(例如,使用 32K 字节缓冲区)来进行复制,从而获得一点性能提升,这至少会消除检查每个字符以查看它是否是行尾字符所花费的时间,就像现在 reader.ReadLine() 发生的那样。

【讨论】:

  • 如果更少,你会如何处理“空闲”空间?用空格填充它?
  • 可能,但这取决于格式。在 CSV 文件中,我可以引用标题元素,并在逗号后添加填充空格。
  • +1。 @Jodrell,是的,在大多数情况下,CSV 会忽略空格 - 因此使用它们进行填充就可以了(我试图在我的相同答案中建议它:))。空格对于大多数编码也是安全的——因此如果需要,可以将其作为字节直接写入流中。
【解决方案2】:

唯一可以显着加快速度的是,如果你真的可以替换第一行。如果新的第一行不长于旧的 - 请小心替换(如果需要,使用空格填充)第一行。

否则 - 您必须创建新文件并在第一行之后复制其余部分。您可以通过将缓冲区大小/显式复制调整为二进制/每个分配大小来优化复制,但这不会改变您需要复制整个文件的事实。

如果您打算将 CSV 数据放入 DB 中,还有一个作弊方法:如果顺序无关紧要,您可以从头开始读取一些行,将它们替换为新标题并将删除的行添加到文件末尾。

旁注:如果这是一次性操作,我只需复制文件并完成它...调试将数据插入文本文件中间的可能具有不同编码的代码可能不值得努力。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-25
    • 1970-01-01
    • 2018-08-05
    • 2011-05-06
    • 2019-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多