У меня более 125 файлов TSV по ~ 100 МБ каждый, которые я хочу объединить. Операция объединения позволяет уничтожить 125 файлов, но не данные. В конце концов, я получаю большой файл содержимого всех файлов один за другим (без определенного порядка).
Есть ли эффективный способ сделать это? Мне было интересно, если Windows предоставляет API, чтобы просто сделать большой "Союз" из всех этих файлов? В противном случае мне придется прочитать все файлы и написать большой.
Спасибо!
Значит, «слияние» - это просто запись файлов один за другим? Это довольно просто - просто откройте один выходной поток, а затем несколько раз откройте входной поток, скопируйте данные, закройте. Например:
static void ConcatenateFiles(string outputFile, params string[] inputFiles)
{
using (Stream output = File.OpenWrite(outputFile))
{
foreach (string inputFile in inputFiles)
{
using (Stream input = File.OpenRead(inputFile))
{
input.CopyTo(output);
}
}
}
}
Используется метод Stream.CopyTo
, который появился впервые в .NET 4. Если вы не используете .NET 4, вам пригодится другой вспомогательный метод:
private static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
}
Ничего подобного. я знаю, что это более эффективно, чем это ... но, что важно, это вообще не займет много памяти в вашей системе. Это не значит, что он постоянно читает весь файл в память, а затем снова все записывает.
РЕДАКТИРОВАТЬ: Как указано в комментариях, есть способы, которыми вы можете поиграть с параметрами файла, чтобы потенциально сделать его немного более эффективным с точки зрения того, что файловая система делает с данными. Но, по сути, вы собираетесь читать данные и записывать их, в любом случае, по очереди.
Сделайте это из командной строки:
copy 1.txt+2.txt+3.txt combined.txt
или
copy *.txt combined.txt
Вы имеете в виду, что с помощью слияния вы хотите решить с помощью некоторой пользовательской логики, какие строки куда идут? Или вы имеете в виду, что вы в основном хотите объединить файлы в один большой?
В случае последнего, возможно, вам вообще не нужно делать это программно, просто создайте один пакетный файл с этим (/b
для двоичного кода, удалите, если он не нужен):
copy /b "file 1.tsv" + "file 2.tsv" "destination file.tsv"
Используя C#, я бы выбрал следующий подход. Напишите простую функцию, которая копирует два потока:
void CopyStreamToStream(Stream dest, Stream src)
{
int bytesRead;
// experiment with the best buffer size, often 65536 is very performant
byte[] buffer = new byte[GOOD_BUFFER_SIZE];
// copy everything
while((bytesRead = src.Read(buffer, 0, buffer.Length)) > 0)
{
dest.Write(buffer, 0, bytesRead);
}
}
// then use as follows (do in a loop, don't forget to use using-blocks)
CopStreamtoStream(yourOutputStream, yourInputStream);