Можно ли удалить символы из сжатого файла, не распаковывая его? - PullRequest
0 голосов
/ 03 марта 2020

У меня есть сжатый файл размером около 200 МБ в виде файла tar.gz. Я понимаю, что могу извлечь файлы xml в нем. Он содержит несколько небольших и один файл размером 5 ГБ xml. Я пытаюсь удалить некоторые символы из файлов xml.

Поэтому мой основной вопрос c таков: возможно ли даже выполнить это sh, не извлекая содержимого сжатого файла? ?

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

1 Ответ

1 голос
/ 04 марта 2020

Вам придется распаковать, изменить, а затем повторно сжать файлы. Обойти это невозможно.

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

Вот пример того, как это сделать:

  1. Создать два случайных файла:
echo "hello world" > a
echo "hello world" > b
Создать сжатый архив, содержащий оба:
tar -c -z -f x.tgz a b
Передача содержимого несжатого архива через чейнджер. К сожалению, я не нашел никакого способа сделать это на основе оболочки, но вы также указали Python в тегах, и с помощью модуля tarfile вы можете добиться этого:

Вот файл tar.py:

#!/usr/bin/env python3

import sys
import tarfile

tar_in  = tarfile.open(fileobj=sys.stdin.buffer,  mode='r:gz')
tar_out = tarfile.open(fileobj=sys.stdout.buffer, mode='w:gz')

for tar_info in tar_in:
  reader = tar_in.extractfile(tar_info)
  if tar_info.path == 'a':  # my example file names are "a" and "b"
    # now comes the code which makes our change:
    # we just skip the first two bytes in each file:
    reader.read(2)  # skip two bytes
    tar_info.size -= 2  # reduce size in info object as well
  # add the (maybe changed) file to the output:
  tar_out.addfile(tar_info, reader)

tar_out.close()
tar_in.close()

Это можно назвать так:

./tar.py < x.tgz > y.tgz

y.tgz снова будет содержать оба файла, но в a первые два байта будут пропущены (поэтому его содержимое будет llo world).

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

Но, как вы сформулировали свой вопрос, это может быть возможно в вашем случае.

Все, что вам нужно сделать, это предоставить файлоподобный объект (может быть Popen выходной поток объекта), такой как reader в моем простом примере.

...