Как эффективно объединить гигантские файлы с C #

У меня более 125 файлов TSV по ~ 100 МБ каждый, которые я хочу объединить. Операция объединения позволяет уничтожить 125 файлов, но не данные. В конце концов, я получаю большой файл содержимого всех файлов один за другим (без определенного порядка).

Есть ли эффективный способ сделать это? Мне было интересно, если Windows предоставляет API, чтобы просто сделать большой "Союз" из всех этих файлов? В противном случае мне придется прочитать все файлы и написать большой.

Спасибо!

8
задан Martin 24 August 2010 в 13:14
поделиться

3 ответа

Значит, «слияние» - это просто запись файлов один за другим? Это довольно просто - просто откройте один выходной поток, а затем несколько раз откройте входной поток, скопируйте данные, закройте. Например:

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);
    }
}

Ничего подобного. я знаю, что это более эффективно, чем это ... но, что важно, это вообще не займет много памяти в вашей системе. Это не значит, что он постоянно читает весь файл в память, а затем снова все записывает.

РЕДАКТИРОВАТЬ: Как указано в комментариях, есть способы, которыми вы можете поиграть с параметрами файла, чтобы потенциально сделать его немного более эффективным с точки зрения того, что файловая система делает с данными. Но, по сути, вы собираетесь читать данные и записывать их, в любом случае, по очереди.

17
ответ дан 5 December 2019 в 07:56
поделиться

Сделайте это из командной строки:

copy 1.txt+2.txt+3.txt combined.txt

или

copy *.txt combined.txt
2
ответ дан 5 December 2019 в 07:56
поделиться

Вы имеете в виду, что с помощью слияния вы хотите решить с помощью некоторой пользовательской логики, какие строки куда идут? Или вы имеете в виду, что вы в основном хотите объединить файлы в один большой?

В случае последнего, возможно, вам вообще не нужно делать это программно, просто создайте один пакетный файл с этим (/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);
2
ответ дан 5 December 2019 в 07:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: