Эффективный способ объединения нескольких текстовых файлов

17

У меня есть несколько файлов текста, которые мне нужно прочитать и объединить в один файл. Файлы имеют разный размер: 1 - 50 МБ каждый. Каков наиболее эффективный способ объединить эти файлы, не нападая на страшный System.OutofMemoryException ?

    
задан Dave Harding 10.06.2011 в 21:47
источник
  • Можете ли вы описать «Объединить»? А что в этих файлах? Просто строки текста или CSV или XML или ... –  Henk Holterman 10.06.2011 в 21:49
  • Какое сочетание вы должны делать? Если вы просто, скажем, объедините сортировку сгруппированных отсортированных файлов, вам не нужно будет считывать целые файлы в памяти, а просто обрабатывать их по очереди. –  Chris Jester-Young 10.06.2011 в 21:49
  • из командной строки: copy <your files> targefile.text –  Muad'Dib 10.06.2011 в 21:50
  • Да ... копировать файл1.txt + file2.txt + file3.txt allfiles.txt –  agent-j 10.06.2011 в 22:05
  • copy * .txt allfiles.txt –  Lee Englestone 04.02.2013 в 10:17

3 ответа

22

Сделайте это в кусках:

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);
            }
        }
    }
}
    
ответ дан Darin Dimitrov 10.06.2011 в 21:50
источник
  • Я должен бежать на встречу и, возможно, не смогу проверить немного, но я вернусь к вам как можно скорее! - Благодаря –  Dave Harding 10.06.2011 в 21:52
  • @Dave Harding, никаких проблем, удачи на встрече :-) –  Darin Dimitrov 10.06.2011 в 21:53
  • Повторное перераспределение и копирование данных в, фактическое является избыточным. Просто напишите количество байт, которое вы знаете, вы читаете (за каждый бит) непосредственно из буфера в новый файл. сам буфер также нужно выделить только один раз, прежде чем вводить внешний цикл. –  Steve Townsend 10.06.2011 в 22:17
  • @Steve Townsend, очень хорошая точка. Я обновил свой пост, чтобы принять его во внимание. –  Darin Dimitrov 10.06.2011 в 23:52
  • Дарин, спасибо. Очень признателен. 10 файлов, и он даже не разбивает пот. –  Dave Harding 13.06.2011 в 18:56
Показать остальные комментарии
22

Дарин на правильном пути. Моя настройка будет следующей:

using (var output = File.Create("output"))
{
    foreach (var file in new[] { "file1", "file2" })
    {
        using (var input = File.OpenRead(file))
        {
            input.CopyTo(output);
        }
    }
}
    
ответ дан n8wrl 10.06.2011 в 21:54
источник
  • CopyTo - хороший, но, вероятно, стоит упомянуть, что он доступен только в .NET 4.0. –  Darin Dimitrov 10.06.2011 в 21:55
  • Oooo - теперь не так. Мой MSDN по умолчанию для .NET 4 –  n8wrl 10.06.2011 в 21:55
  • CopyTo - MSDN: bit.ly/16rzEMF –  Ron Klein 16.08.2013 в 11:08
  • как мы получим файлы из объединенного файла? –  KADEM Mohammed 06.12.2013 в 13:52
  • @Carter: Не могли бы вы уточнить? Исходные файлы все еще существуют –  n8wrl 07.12.2013 в 14:24
Показать остальные комментарии
-1

Это код, используемый выше для .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());
    }
  }
}

Обратите внимание, что это сразу прочитает весь файл в памяти. Это означает, что большие файлы будут использовать много памяти (и если недостаточно памяти, она может не работать вместе).     

ответ дан user2606127 22.07.2013 в 10:45
источник
  • -1: Это не будет работать для больших файлов (в результате ReadToEnd () создаст строку в памяти. –  Oliver 22.07.2013 в 13:41