Как прочитать несколько текстовых файлов и сохранить их в один текстовый файл? - PullRequest
1 голос
/ 20 мая 2009

В моем случае у меня есть пять огромных текстовых файлов, которые я должен встроить в один текстовый файл.

Я пытался с StreamReader (), но я не знаю, как заставить его прочитать еще один файл, мне нужно назначить другую переменную?

Показывая пример, мы будем очень признательны.

Ответы [ 2 ]

8 голосов
/ 20 мая 2009

Новый ответ

(См. Объяснение оригинального ответа на шутки ниже.)

static void CopyFiles(string dest, params string[] sources)
{
    using (TextWriter writer = File.CreateText(dest))
    {
        // Somewhat arbitrary limit, but it won't go on the large object heap
        char[] buffer = new char[16 * 1024]; 
        foreach (string source in sources)
        {
            using (TextReader reader = File.OpenText(source))
            {
                int charsRead;
                while ((charsRead = reader.Read(buffer, 0, buffer.Length)) > 0)
                {
                    writer.Write(buffer, 0, charsRead);
                }
            }
        }
    }
}

Этот новый ответ очень похож на подход Мартина, за исключением:

  • Читает в меньший буфер; 16K будет приемлемым практически во всех ситуациях, и не попадет в кучу больших объектов (которая не уплотняется)
  • Считывает текст данные вместо двоичных данных по двум причинам:
    • Код можно легко изменить для преобразования из одной кодировки в другую
    • Если каждый входной файл содержит метку порядка байтов, которая будет пропущена читателем, вместо того чтобы заканчиваться метками порядка байтов, разбросанными по выходному файлу на границах входного файла

Оригинальный ответ

Мартин Стеттнер указал на проблему в ответе ниже - если первый файл заканчивается без новой строки, он все равно создаст новую строку в выходном файле. Кроме того, он будет переводить новые строки в "\ r \ n", даже если раньше они были просто "\ r" или "\ n". Наконец, это бессмысленно рискует использовать большие объемы данных для длинных строк.

Что-то вроде:

static void CopyFiles(string dest, params string[] sources)
{
    using (TextWriter writer = File.CreateText(dest))
    {
        foreach (string source in sources)
        {
            using (TextReader reader = File.OpenText(source))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    writer.WriteLine(line);
                }
            }
        }
    }
}

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

static void CopyFiles(string dest, params string[] sources)
{
    using (TextWriter writer = File.CreateText(dest))
    {
        foreach (string source in sources)
        {
            string text = File.ReadAllText(source);
            writer.Write(text);
        }
    }
}
2 голосов
/ 20 мая 2009

Редактировать

Как отметил Джон Скит, текстовые файлы обычно должны обрабатываться иначе, чем двоичные файлы. ,

Я просто оставляю этот ответ, так как он может быть более производительным, если у вас действительно большие файлы, и вас не ограничивают проблемы с кодировкой (например, разные входные файлы имеют разные кодировки или несколько знаков порядка байтов в выходной файл):

public void CopyFiles(string destPath, string[] sourcePaths) {
  byte[] buffer = new byte[10 * 1024 * 1024]; // Just allocate a buffer as big as you can afford
  using (var destStream= = new FileStream(destPath, FileMode.Create) {
    foreach (var sourcePath in sourcePaths) {
      int read;
      using (var sourceStream = FileStream.Create(sourcePath, FileMode.Open) {
        while ((read = sourceStream.Read(buffer, 0, 10*1024*1024)) != 0)
          destStream.Write(buffer, 0, read);
      }
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...