@uuuu

Как разделить большой файл?

У меня есть файл 4 гб, но на сервере я могу хранить только 2 гб.
Как мне разделить, скачать и соединить файл в один?
  • Вопрос задан
  • 198 просмотров
Пригласить эксперта
Ответы на вопрос 3
gedev
@gedev
сисадмин-энтузиаст
Сделать можно через split и cat.
Ответ написан
Diman89
@Diman89
В том же total commander: файл/разбить(собрать)
Ответ написан
vabka
@vabka Куратор тега C#
Токсичный шарпист
using System;
using System.IO;
using System.Linq;

var command = args[0];
if (command == "split")
{
   // Чтобы разбить файл, нужно передать команду split ./path/to/file/test
    // В итоге в текущей папке появится папка result с чанками по 2кб, которые будут называться, как оригинальный файл, но с номером на конце.
   // например ./result/test1
   // ./result/test2 итд
    var filePath = args[1];
    const int chunkSize = 2 * 1024; // 2 KB
    await using var src = File.OpenRead(filePath);
    var fileName = Path.GetFileName(filePath);
    var chunkNo = 0;
    var buffer = new Memory<byte>(new byte[1024]); // 1 KB buffer

    Directory.CreateDirectory("result");
    var bytesInChunkWritten = 0;
    var currentChunk = File.OpenWrite(Path.Combine(Directory.GetCurrentDirectory(), "result", fileName + chunkNo));

    while (true)
    {
        var bytesRead = await src.ReadAsync(buffer);
        await currentChunk.WriteAsync(buffer[..bytesRead]);
        if (bytesRead < buffer.Length)
            break;
        bytesInChunkWritten += bytesRead;
        if (bytesInChunkWritten >= chunkSize)
        {
            await currentChunk.DisposeAsync();
            chunkNo += 1;
            currentChunk = File.OpenWrite(Path.Combine(Directory.GetCurrentDirectory(), "result", fileName + chunkNo));
            bytesInChunkWritten = 0;
        }
    }
}
else if (command == "merge")
{
    // Чтобы склеить файлы - нужно передать команду merge с путём к папке со всеми чанками и оригинальным названием файла
   // Например если оригинальный файл назывался test, то нужно дать команду merge ./result/test
  // В итоге в папке ./result появится оригнальный файл test
    var filePath = Path.GetFullPath(args[1]);
    var dir = Path.GetDirectoryName(filePath);
    var fileName = Path.GetFileName(filePath);
    // Сортируем все чанки в правильном порядке
    var chunks = Directory.GetFiles(dir!, fileName + "*")
        .Where(x => x.Length > filePath.Length)
        .OrderBy(x => int.Parse(x[filePath.Length..]));
    // Создаём файл
    var dest = File.OpenWrite(Path.Combine(dir, fileName));
    // Перекладываем всё в него
    foreach (var chunk in chunks)
    {
        await using var file = File.OpenRead(chunk);
        await file.CopyToAsync(dest);
    }
}

Накидал за пару минут пример, который вполне успешно делит файлы на куски по 2кб и склеивает обратно.
Код не идеален, да и сам алгоритм можно улучшить - например добавить хэш оригинального файла, чтобы можно было проверить целостность, или разбивать на произвольные куски.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы