Как можно объединить два огромных файла, имея очень мало свободного места на диске?[закрыто]

StackOverflow https://stackoverflow.com/questions/290700

Вопрос

Предположим, у вас есть два огромных файла (несколько ГБ), которые вы хотите объединить, но у вас очень мало свободного места на диске (скажем, пара сотен МБ).То есть, учитывая file1 и file2, вы хотите получить один файл, который является результатом объединения file1 и file2 вместе побайтно и удалите исходные файлы.

Вы не можете сделать очевидное cat file2 >> file1; rm file2, поскольку между этими двумя операциями у вас закончится место на диске.

Приветствуются решения на любых платформах с бесплатными или платными инструментами;Это гипотетическая проблема, которую я придумал на днях, когда загружал ISO-образ Linux, и загрузка была прервана на полпути из-за сбоя беспроводной связи.

Это было полезно?

Решение

Я думаю, что сложность заключается в том, чтобы определить, как пространство можно восстановить из исходных файлов.

Я думаю, что может сработать следующее:

<Ол>
  • Выделите разреженный файл комбинированный размер.
  • Скопируйте 100 МБ из конца второго файла в конец нового файла.
  • Обрезать 100 МБ конца второго файла
  • Цикл 2 и 3, пока вы не закончите второй файл (с изменением 2. в правильное место в файле назначения).
  • Сделайте 2 и 3 и 4, но с первым файлом.
  • Все это зависит от разреженной поддержки файлов и немедленного освобождения места усечения файла.

    Если вы действительно хотели это сделать, вам следует изучить команду dd . который может сделать шаг копирования

    Кто-то в другом ответе дал аккуратное решение, которое не требует разреженных файлов, но дважды копирует file2:

    <Ол>
  • Скопируйте 100-мегабайтные фрагменты из конца файла 2 в новый файл 3, получив в обратном порядке. Усечение файла 2 на ходу.
  • Скопируйте 100-мегабайтные фрагменты из конца файла 3 в файл 1, в результате чего фрагменты в их исходном порядке заканчиваются в конце файла 1. Обрезание файла 3 по ходу работы.
  • Другие советы

    время, потраченное на поиск умного решения, включающего перестановку секторов диска и манипулирование цепочкой файлов: 2-4 часа

    время, потраченное на приобретение / написание программного обеспечения для копирования и усечения на месте: 2-20 часов

    среднеквадратичное значение для программиста 50 долларов в час: 400–1200 долларов

    стоимость USB-накопителя емкостью 1 ТБ: 100-200 долларов США

    способность понимать фразу "альтернативная цена": бесценно

    Вот небольшое улучшение по сравнению с моим первый ответ .

    Если у вас есть 100 МБ свободного места, скопируйте последние 100 МБ из второго файла и создайте третий файл. Обрежьте второй файл, чтобы он стал на 100 МБ меньше. Повторяйте этот процесс, пока второй файл не будет полностью разложен на отдельные фрагменты размером 100 МБ.

    Теперь каждый из этих файлов размером 100 МБ может быть добавлен к первому файлу, по одному за раз.

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

    Другими словами, забудьте о перестановке любых блоков содержимого файла, просто отредактируйте информацию об этих файлах.

    если файл легко сжимается (т. е. журналы):

    gzip file1
    
    gzip file2
    
    zcat file1 file2 | gzip > file3
    
    rm file1
    
    rm file2
    
    gunzip file3
    

    Опасаясь звучать легкомысленно, рассматривали ли вы вариант получения большего диска? Вероятно, это было бы быстрее ...

    Не очень эффективно, но я думаю, что это можно сделать.

    Откройте первый файл в режиме добавления и копируйте в него блоки из второго файла, пока диск не будет почти заполнен. Для оставшейся части второго файла скопируйте блоки с того места, где вы остановились, в начало файла с помощью ввода-вывода с произвольным доступом. Обрежьте файл после того, как вы скопировали последний блок. Повторяйте, пока не закончите.

    Очевидно, что экономический ответ заключается в том, чтобы купить больше памяти при условии, что это возможный ответ. Однако это может быть не так - встроенная система, в которой нет возможности подключить больше хранилища или нет доступа к самому оборудованию, например, космический зонд в полете.

    Ранее представленный ответ, основанный на разреженной файловой системе, хорош (кроме деструктивного характера, если что-то идет не так!), если у вас разреженная файловая система. Что если ты этого не сделаешь?

    Начиная с конца файла 2, копируйте блоки в начало целевого файла, меняя их по ходу. После каждого блока вы усекаете исходный файл до не скопированной длины. Повторите для файла № 1.

    В этот момент целевой файл содержит все данные в обратном направлении, исходные файлы исчезли.

    Считайте блок с торта и с конца целевого файла, переверните его и запишите в место, откуда пришел другой. Пройдите внутрь, переворачивая блоки.

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

    ок, для теоретического развлечения, и только если вы пообещаете не тратить время на это:

    • файлы хранятся на диске по частям
    • части соединены в цепочку

    Таким образом, вы можете объединить файлы:

    • связывание последней части первого файла с первой частью последнего файла
    • изменение записи каталога для первого файла, чтобы изменить последний фрагмент и размер файла
    • удаление записи каталога для последнего файла
    • очистка маркера конца первого файла, если таковой имеется
    • обратите внимание: если последний сегмент первого файла заполнен лишь частично, вам придется скопировать данные «вверх» по сегментам последнего файла, чтобы избежать мусора в середине файла [спасибо @Wedge!]

    Это было бы оптимально эффективно:минимальные изменения, минимальное копирование, свободное место на диске не требуется.

    теперь иди купи USB-накопитель ;-)

    Две мысли:

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

    Временно уменьшите дисковое пространство, используемое функциональностью ОС (например, виртуальной памятью, «корзиной» или подобной). Вероятно, только для использования в Windows.

    Я сомневаюсь, что это прямой ответ на вопрос. Вы можете рассматривать это как альтернативный способ решения проблемы.

    Я думаю, что второй файл можно рассматривать как часть 2 первого файла. Обычно в zip-приложении мы видим, что огромный файл разбит на несколько частей. Если вы откроете первую часть, приложение автоматически рассмотрит другие части при дальнейшей обработке.

    Мы можем смоделировать то же самое здесь. Как указал @edg, возиться с файловой системой можно было бы в одном направлении.

    вы могли бы сделать это:

    head file2 --bytes=1024 >> file1 && tail --bytes=+1024 file2 >file2 
    

    вы можете увеличить 1024 в зависимости от того, сколько дополнительного дискового пространства у вас есть, а затем просто повторять это, пока все байты не будут перемещены.

    Это, вероятно, самый быстрый способ сделать это (с точки зрения времени разработки)

    Вы можете получить дополнительное пространство, сжимая всю файловую систему. Я полагаю, что NTFS поддерживает это, и я уверен, что есть разновидности файловых систем * nix, которые поддержали бы это. Кроме того, было бы полезно после копирования файлов у вас все еще иметь больше места на диске, чем при запуске.

    Хорошо, немного изменив проблему. Скорее всего, на диске есть другие вещи, которые вам не нужны, но вы не знаете, что это и где это. Если бы вы могли найти его, вы могли бы удалить его, а затем, возможно, у вас было бы достаточно свободного места.

    Чтобы найти эти "опухоли", будь то несколько больших или много маленьких, я использую небольшую программу отбора проб. Начиная с вершины каталога (или корня), он делает два прохода. На этапе 1 он проходит по дереву каталогов, складывая размеры всех файлов, чтобы получить всего N байтов. На этапе 2 он снова обходит дерево каталогов, делая вид, что читает каждый файл. Каждый раз, когда он пропускает N / 20 байт, он печатает путь к каталогу и имя файла, который он «читает». Таким образом, конечный результат - 20 глубоких выборок имен путей, равномерно распределенных по всем байтам в каталоге.

    Тогда просто взгляните на этот список, чтобы найти то, что вам не нужно, и идите и сдуйте его.

    (Это пространственный эквивалент метода выборки, который я использую для оптимизации производительности.)

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top