Форум сайта python.su
0
Всем доброго времени суток !
Возникла необходимость срочно написать небольшой скрипт именно на Python, а т.к. знания языка у меня пока полный ноль, обращаюсь к знатокам.
На входе - бинарный файл (стоковая прошивка одного из устройств на базе Android).
Структура очень проста (с нулевой позиции):
00 00 00 00 - 'Тег' (всегда 0x00 0x00 0x00 0x00); 0F 00 00 00 - 'Длина пути и имени файла' (unsigned int); 00 20 79 01 - 'Размер файла' (unsigned int); xx xx xx xx - 'Путь и имя файла' == 'значению' "Длина пути и имени файла" xx xx xx xx - 'Контент' == 'значению' "Размер файла"
0000000: 00 00 00 00 0f 00 00 00 00 20 79 01 2f 69 6d 61 '......... y./ima' 0000010: 67 65 2f 61 6d 73 73 2e 6d 62 6e 7f 45 4c 46 01 'ge/amss.mbn.ELF.' .................. 1792010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0f '................' 1792020: 00 00 00 00 80 3d 00 2f 69 6d 61 67 65 2f 62 6f '.....=./image/bo' 1792030: 6f 74 2e 69 6d 67 41 4e 44 52 4f 49 44 21 04 f0 'ot.imgANDROID!..'
Отредактировано Dumonde (Май 12, 2012 12:17:48)
Офлайн
173
“Взаимоисключающе” как-то звучит:
Dumondeи
Возникла необходимость срочно написать небольшой скрипт именно на Python
DumondeНе проще воспользоваться тем, в чем есть знания?
а т.к. знания языка у меня пока полный ноль
#!/usr/bin/env python # -*- coding: utf-8 -*- import os import struct def iter_bin_image(filename): """ Yields name, file_size, file_data """ image_size = os.path.getsize(filename) with open(filename, 'rb') as f: while f.tell() < image_size: tag, name_size, file_size = struct.unpack('III', f.read(12)) name = f.read(name_size) yield name, file_size, f.read(file_size) def extract_image(img_filename, output_folder='output'): if not os.path.exists(output_folder): os.makedirs(output_folder) for filename, size, data in iter_bin_image(img_filename): filename = filename.lstrip('/') filename = os.path.join(output_folder, os.path.normpath(filename)) folder, name = os.path.split(filename) if not os.path.exists(folder): os.makedirs(folder) print('Saving: {} ({} bytes)'.format(filename, size)) with open(filename, 'wb') as f: f.write(data) if __name__ == "__main__": extract_image('data.dat')
Отредактировано reclosedev (Май 12, 2012 14:45:18)
Офлайн
0
Отлично, большое спасибо за столь быстрый рабочий скрипт.
reclosedevВ данном случае не проще, т.к. есть большой скрипт именно на питоне и добавить данную потрошилку рациональнее именно в него.
“Взаимоисключающе” как-то звучит…
Не проще воспользоваться тем, в чем есть знания?
reclosedevРазмер данных 100-400 Мб. Проверку попробую сам вставить по аналогии.
Но тут данные одного файла читаются полностью в память. Не знаю, на сколько они большими могут быть. И ошибки никакие не проверяются.
Офлайн
3
я честно скажу никогда раньше не занимался бинарными файлами на питонах.
стало интересно - вот что получилось.
import sys
import struct
def write_file_out(info, dirprefix):
with open(dirprefix + info['path'], 'w') as f:
f.write(info['content'])
def parse_files(binfile, prefix):
while True:
info = {}
info['name_length'] = struct.unpack('i', binfile.read(4))[0]
info['file_size'] = struct.unpack('i', binfile.read(4))[0]
info['path'] = struct.unpack('s', binfile.read(info['name_length']))
info['content'] = binfile.read(info['file_size'])
yield info
def parse_main_file(path, dirprefix):
with open(path, 'rb') as binfile:
#read tag
tag = binfile.read(4)
#parse files and write em out
try:
for fileinfo in parse_files(binfile):
write_file_out(fileinfo, dirprefix)
except:
pass
def main():
parse_main_file(sys.argv[1], sys.argv[2])
if __name__ == '__main__':
main()
Офлайн
0
dehunТак же благодарю за оперативность. Но пока не получилось ничего извлечь с помощью данного скрипта.
стало интересно - вот что получилось.
а можно файлик ешё для теста? а то я написать то написал но не запускал даже - неначем
Отредактировано Dumonde (Май 12, 2012 15:39:29)
Офлайн
0
Залил небольшой файлик для теста http://rghost.ru/38053132
Офлайн
173
DumondeЕсли каждый файл может быть размером ~30 МБ, тогда лучше читать и писать частями:
Размер данных 100-400 Мб.
#!/usr/bin/env python # -*- coding: utf-8 -*- import os import struct def extract_image(img_filename, output_folder='output'): if not os.path.exists(output_folder): os.makedirs(output_folder) with open(img_filename, 'rb') as img_fp: for filename, size in iter_bin_image(img_fp): filename = filename.lstrip('/') filename = os.path.join(output_folder, os.path.normpath(filename)) folder, name = os.path.split(filename) if not os.path.exists(folder): os.makedirs(folder) print('Saving: {} ({} bytes)'.format(filename, size)) with open(filename, 'wb') as output: copy_bytes(img_fp, output, size) def iter_bin_image(img_fp): """ Yields name, file_size. Allows to iter name/size without data consuming """ image_size = os.fstat(img_fp.fileno()).st_size while img_fp.tell() < image_size: tag, name_size, file_size = struct.unpack('III', img_fp.read(12)) name = str(img_fp.read(name_size)) next_pos = img_fp.tell() + file_size yield name, file_size img_fp.seek(next_pos, os.SEEK_SET) def copy_bytes(source_fp, dest_fp, bytes_to_copy, buff_size=1024*1024): while bytes_to_copy: if buff_size > bytes_to_copy: buff_size = bytes_to_copy data = source_fp.read(buff_size) if len(data) < buff_size: raise IOError('Unexpected end of file') dest_fp.write(data) bytes_to_copy -= buff_size
Офлайн