Правильно ли проводить различие между сжатыми файлами.gz и заархивированными файлами tar.gz?
Как правильно различать простой сжатый файл в формате gzip или bzip2 (например,.gz) и архив, сжатый с помощью gzip или bzip2 (например,.tar.gz). Идентификация с использованием расширений суффиксов не является надежным вариантом. как это возможно файлы могут быть переименованы.
Теперь в командной строке я могу сделать что-то вроде этого:
bzip2 -dc test.tar.bz2 |head|file -
Поэтому я попытался сделать что-то подобное в python с помощью следующей функции:
def get_magic(self, store_file, buffer=False, look_deeper=False):
# see what we're indexing
if look_deeper == True:
m = magic.Magic(mime=True, uncompress=True)
else:
m = magic.Magic(mime=True)
if buffer == False:
try:
file_type = m.from_file(store_file)
except Exception, e:
raise e
else:
try:
file_type = m.from_buffer(store_file)
except Exception, e:
raise e
return file_type
Затем, при попытке прочитать сжатый архив, я передам в буфер из другого места через:
file_buffer = open(file_name).read(8096)
archive_check = self.get_magic(file_buffer, True, True)
К сожалению, это становится проблематичным при использовании флага uncompress в python-magic, потому что кажется, что python-magic ожидает, что я передам весь файл, хотя я только хочу, чтобы он прочитал буфер. Я заканчиваю с исключением:
bzip2 ERROR: Compressed file ends unexpectedly
Учитывая, что файлы, на которые я смотрю, могут иметь размер от 2 до 20 ГБ, это становится довольно проблематичным. Я не хочу читать весь файл.
Можно ли его взломать, отключить конец сжатого файла и добавить его в буфер? Лучше ли игнорировать идею распаковки файла с помощью python-magic и вместо этого делать это, прежде чем передать в буфер для идентификации через:
file_buffer = open(file_name, "r:bz2").read(8096)
Есть ли способ лучше?
2 ответа
Весьма вероятно, что tar-файл имеет несжатые данные со смещением 257 "ustar" или если несжатые данные в целом составляют 1024 нулевых байта (пустой tar-файл).
Вы можете прочитать только первые 1024 байта несжатых данных, используя z = zlib.decompressobj()
или же z = bz2.BZ2Decompressor()
, а также z.decompress()
,
Я на самом деле собираюсь отметить ответ Марка как правильный, поскольку он дал мне подсказку.
Я закончил тем, что бросил проект, чтобы заняться другими делами в течение хороших шести месяцев, и был озадачен, так как bz2.BZ2Decompressor, похоже, не работал так, как предполагалось. Оказывается, проблема не решаема в 1024 байта.
#!/usr/bin/env python
import os
import bz2
import magic
store_file = "10mb_test_file.tar.bz2"
m = magic.Magic(mime=True)
file_buffer = open(store_file, "rb").read(1000000)
buffer_chunk = ""
decompressor = bz2.BZ2Decompressor()
print ( "encapsulating bz2" )
print ( type(file_buffer) )
print ( len(file_buffer) )
file_type = m.from_buffer(file_buffer)
print ( "file type: %s :" % file_type)
buffer_chunk += decompressor.decompress( file_buffer )
print ( "compressed file contents" )
print ( type(buffer_chunk) )
print ( len(buffer_chunk) )
file_type = m.from_buffer(buffer_chunk)
print ( "file type: %s :" % file_type)
Странно, но с файлом tar.bz2 размером 20 МБ я могу использовать значение 200 000 байт, а не 1 000 000 байт, но это значение не будет работать с тестовым файлом 10 МБ. Я не знаю, является ли он специфичным для задействованного архива tar.bz2, и я не изучал задействованные алгоритмы, чтобы увидеть, находятся ли они в определенных точках, но чтение примерно 10 МБ данных до сих пор работает на каждом архивном файле. до 5 ГБ. Open(). Read(buffer) будет читать до размера буфера или EOF, так что все в порядке.