【问题标题】:Efficient way to combine multiple text files组合多个文本文件的有效方法
【发布时间】:2011-09-12 18:32:14
【问题描述】:

我有多个文本文件需要阅读并合并到一个文件中。 这些文件大小不一:每个 1 - 50 MB。 什么是合并这些文件而不碰到可怕的System.OutofMemoryException 的最有效方法?

【问题讨论】:

  • 你能描述一下“组合”吗?这些文件中有什么?只是文本行或 CSV 或 XML 或 ...
  • 你需要做什么样的组合?如果您只是对一堆已排序的文件进行合并排序,则无需将整个文件读入内存,而是可以逐行处理它们。
  • 从命令提示符:复制 targefile.text
  • 是的...复制file1.txt + file2.txt + file3.txt allfiles.txt
  • copy *.txt allfiles.txt

标签: c# performance concatenation


【解决方案1】:

分块做:

const int chunkSize = 2 * 1024; // 2KB
var inputFiles = new[] { "file1.dat", "file2.dat", "file3.dat" };
using (var output = File.Create("output.dat"))
{
    foreach (var file in inputFiles)
    {
        using (var input = File.OpenRead(file))
        {
            var buffer = new byte[chunkSize];
            int bytesRead;
            while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
            {
                output.Write(buffer, 0, bytesRead);
            }
        }
    }
}

【讨论】:

  • 我要去开会,可能暂时无法测试,但我会尽快回复您! - 谢谢
  • actual 的重复重新分配和数据复制是多余的。只需直接从buffer 写出你知道你读取的字节数(每个bytesread)到新文件中。 buffer 本身也只需要分配一次,就可以进入外部的for 循环。
  • @Steve Townsend,非常好的观点。我已经更新了我的帖子以考虑到这一点。
  • 达林,谢谢。非常感激。 10 个文件,它甚至不费吹灰之力。
  • @DarinDimitrov 这也处理 unicode 文件吗?如果两个文件的格式不同怎么办?
【解决方案2】:

达林走在正确的轨道上。我的调整是:

using (var output = File.Create("output"))
{
    foreach (var file in new[] { "file1", "file2" })
    {
        using (var input = File.OpenRead(file))
        {
            input.CopyTo(output);
        }
    }
}

【讨论】:

  • CopyTo 很不错,但值得一提的是它仅在 .NET 4.0 中可用。
  • 噢——现在没有。我的 MSDN 默认为 .NET 4
  • 我们如何从组合文件中取回文件?
  • @Carter:你能澄清一下吗?原始文件仍然存在
  • 是的,在我的情况下,我有两个文件“file.Docx”和“file_Information.Xml”,例如,我希望应用程序 A 将这两个文件合并到一个文件“file.QAF”中。 .然后将此文件传递给另一个应用程序B以恢复两个文件“file.Docx”和“file_Information.Xml”(返回的方式......)
【解决方案3】:

这是上面用于 .Net 4.0 的代码,但与 .Net 2.0 兼容(用于文本文件)

using (var output = new StreamWriter("D:\\TMP\\output"))
{
  foreach (var file in Directory.GetFiles("D:\\TMP", "*.*"))
  {
    using (var input = new StreamReader(file))
    {
      output.WriteLine(input.ReadToEnd());
    }
  }
}

请注意,这将一次读取内存中的整个文件。这意味着大文件将导致使用大量内存(如果没有足够的内存可用,它可能会一起失败)。

【讨论】:

  • -1:这不适用于大文件(因为ReadToEnd() 会在内存中创建一个字符串。
猜你喜欢
  • 1970-01-01
  • 2014-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-16
相关资源
最近更新 更多