Задать вопрос
@uuuu

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

У меня есть файл 4 гб, но на сервере я могу хранить только 2 гб.
Как мне разделить, скачать и соединить файл в один?
  • Вопрос задан
  • 240 просмотров
Подписаться 1 Простой 9 комментариев
Пригласить эксперта
Ответы на вопрос 3
gedev
@gedev
сисадмин-энтузиаст
Сделать можно через split и cat.
Ответ написан
Diman89
@Diman89
В том же total commander: файл/разбить(собрать)
Ответ написан
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кб и склеивает обратно.
Код не идеален, да и сам алгоритм можно улучшить - например добавить хэш оригинального файла, чтобы можно было проверить целостность, или разбивать на произвольные куски.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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