参考链接: Python中的打包pack和拆包unpack参数
.pkg文件的格式
[四字节] 固定的内容, 值不重要 [四字节] 文件数目(unsigned int) [四字节] 文件名表 的偏移(unsigned int) [四字节] 文件名表 的长度(字节数)(unsigned int) …… 中间一堆 各个文件的内容, 文件内容使用zlib压缩过 …… 直到 文件名表: [两字节] 文件名长度 [文件名长度那么多字节] 文件名 [四字节] 固定的内容,值不重要 [四字节] 文件原长度 [四字节] 文件偏移 [四字节] 文件压缩后的长度 [两字节] 又一个文件名的长度 …
例程: 打包 PKGEncode.py 用法 python PKGEncode.py dirname pathname.pkg
# -*- coding: utf-8 -*-
import zlib, glob, os, sys, struct
filelist = []
class FileVisitor:
def __init__(self, startDir=os.curdir):
self.startDir = startDir
def run(self):
for dirname, subdirnames, filenames in os.walk(self.startDir, True):
for filename in filenames:
self.visit_file(os.path.join(dirname, filename))
def visit_file(self, pathname):
filelist.append({'filename':pathname, 'size':0, 'zlib_size':0, 'offset':0, 'relative_filename': pathname.replace(os.path.normpath(self.startDir)+os.sep, '')})
#print filelist[-1]['relative_filename']
if __name__ == "__main__":
if len(sys.argv[1]) < 3:
print 'few parameter'
else:
source_dirname = sys.argv[1]
out_filename = sys.argv[2]
FileVisitor(source_dirname).run()
total = len(filelist)
fp = file(out_filename + '~', 'wb')
fp.write('\x64\x00\x00\x00')
fp.write(struct.pack('I', len(filelist)))
fp.write(struct.pack('I', 0))
fp.write(struct.pack('I', 0))
offset = 16
for index in range(total):
item = filelist[index]
item['offset'] = offset
infile = file(item['filename'], 'rb')
text = infile.read()
infile.close()
item['size'] = len(text)
text = zlib.compress(text)
item['zlib_size'] = len(text)
fp.write(text)
offset += item['zlib_size']
print u'已压缩文件 %d/%d' % (index+1, total)
filename_table_offset = offset
for index in range(total):
item = filelist[index]
fp.write(struct.pack('H', len(item['relative_filename'])))
fp.write(item['relative_filename'])
fp.write('\x01\x00\x00\x00')
fp.write(struct.pack('I', item['offset']))
fp.write(struct.pack('I', item['size']))
fp.write(struct.pack('I', item['zlib_size']))
offset += 2 + len(item['relative_filename']) + 16
print u'已输出路径 %d/%d' % (index+1, total)
filename_table_len = offset - filename_table_offset
fp.close()
fp = file(out_filename + '~', 'rb')
ret = file(out_filename, 'wb')
fp.read(16)
ret.write('\x64\x00\x00\x00')
ret.write(struct.pack('I', len(filelist)))
ret.write(struct.pack('I', filename_table_offset))
ret.write(struct.pack('I', filename_table_len))
copy_bytes = 16
total_bytes = offset
while True:
text = fp.read(2**20)
ret.write(text)
copy_bytes += len(text)
print u'最后的拷贝 %d%%' % (copy_bytes*100.0/total_bytes)
if not text:
break
fp.close()
ret.close()
os.remove(out_filename + '~')
解包 PKGDecode.py 用法 python PKGDecode.py pathname.pkg dirname
# -*- coding: utf-8 -*-
import sys, os, struct, zlib
if __name__ == "__main__":
if len(sys.argv) < 3:
print 'few argument'
else:
pkgfilename = sys.argv[1]
outdirname = sys.argv[2]
pkgfile = file(pkgfilename, 'rb')
pkgfile.read(4)
filenums, = struct.unpack('I', pkgfile.read(4))
filename_table_offset, = struct.unpack('I', pkgfile.read(4))
filename_table_len, = struct.unpack('I', pkgfile.read(4))
pkgfile.seek(filename_table_offset)
for index in range(filenums):
name_len, = struct.unpack('H', pkgfile.read(2))
name = pkgfile.read(name_len)
pkgfile.read(4)
offset, = struct.unpack('I', pkgfile.read(4))
size, = struct.unpack('I', pkgfile.read(4))
zlib_size, = struct.unpack('I', pkgfile.read(4))
current_pos = pkgfile.tell()
pkgfile.seek(offset)
text = pkgfile.read(zlib_size)
text = zlib.decompress(text)
pkgfile.seek(current_pos)
outfilename = os.path.join(outdirname, os.path.join(os.path.splitext(os.path.basename(pkgfilename))[0], name))
print u'进度 [%d/%d]: ' %(index+1, filenums), os.path.join(os.path.splitext(os.path.basename(pkgfilename))[0], name)
if not os.path.exists(os.path.dirname(outfilename)):
os.makedirs(os.path.dirname(outfilename))
file(outfilename, 'wb').write(text)
感谢python各种库的方便 这两个程序也可以作为自己的压缩解压工具
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。