前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >pkg文件--一种简单的游戏资源打包格式

pkg文件--一种简单的游戏资源打包格式

作者头像
用户7886150
修改2020-11-24 11:13:06
2K0
修改2020-11-24 11:13:06
举报
文章被收录于专栏:bit哲学院bit哲学院

参考链接: 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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档