Новый ответ
(См. Объяснение оригинального ответа на шутки ниже.)
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);
}
}
}