zerglurker 发表于 2019-7-6 09:21

pak文件解析代码

最近遇到一个pak文件,网上都是各种解析工具,但是感觉都不敢用
干脆自己写一个,现在发出来,方便大家一起使用
附件有一个测试用的pak文件
代码如下:
import os
import struct


class Binary:
    def __init__(self, data: ):
      self.index = 0
      if isinstance(data, bytearray):
            self.data = data
      elif isinstance(data, bytes):
            self.data = bytearray(data)
      elif isinstance(data, str):
            self.data = bytearray(data.encode(encoding='utf-8'))
      else:
            raise TypeError('data type is invalid:', data.__class__.__name__)
      self.size = len(self.data)

    def read_int8(self) -> int:
      ret = self.data
      self.index += 1
      return ret

    def read_int16(self) -> int:
      ret, = struct.unpack('h', self.data)
      self.index += 2
      return ret

    def read_int32(self) -> int:
      ret, = struct.unpack('i', self.data)
      self.index += 4
      return ret

    def read_int64(self) -> int:
      ret, = struct.unpack('q', self.data)
      self.index += 8
      return ret

    def read_string(self) -> str:
      pass

    def read_bytes(self, size: int) -> bytearray:
      if size > self.rest():
            ret = self.data
            self.index += self.rest()
            return ret
      ret = self.data
      self.index += size
      return ret

    def __len__(self):
      return len(self.data)

    def rest(self) -> int:
      return len(self.data) - self.index

    @staticmethod
    def bytes2str(data: ):
      out = ''
      if data is None or len(data) == 0:
            return 'Null'
      for b in data:
            if out:
                out += ','
            out += '0x%02X' % b
      out += '\n'
      out += data.decode('utf-8')
      return out


class PakData:
    def __init__(self, br: Binary):
      self.version = br.read_int32()
      self.count = br.read_int32()
      self.coding = br.read_int8()
      self.resources = list()
      for i in range(self.count):
            item = {
                'id': br.read_int16(),
                'offset': br.read_int32(),
                'data': bytearray(),
                'size': 0
            }
            self.resources.append(item)
      for i, item in enumerate(self.resources):
            if i + 1 < self.count:
                item['size'] = self.resources['offset'] - item['offset']
            else:
                item['size'] = len(br) - item['offset']
            item['data'] = br.data:item['offset'] + item['size']]


class PakFile:
    def __init__(self, path: str):
      self.path = path
      if os.path.exists(path):
            self.decode()
            return
      self.data = None

    def set_path(self, path):
      self.path = path

    def decode(self) -> int:
      if os.path.exists(self.path) is False:
            return -1
      with open(self.path, mode='rb') as file:
            raw = bytearray(file.read())
            file.close()
            br = Binary(raw)
            self.data = PakData(br)


def main():
    pak = PakFile(r'.\zh-CN.pak')
    if isinstance(pak.data, PakData):
      print('版本:', pak.data.version)
      print('数量:', pak.data.count)
      print('编码:', pak.data.coding)
      for i in range(pak.data.count):
            print('ID:', pak.data.resources['id'])
            print('偏移:', pak.data.resources['offset'])
            print('大小:', pak.data.resources['size'])
            print('内容:', Binary.bytes2str(pak.data.resources['data']))


if __name__ == '__main__':
    main()

zerglurker 发表于 2019-7-6 09:26

注意:
1 如果你已经有pak文件了,请不要下载附件
2 pak文件结构非常简单
版本 4字节 数量 4字节 编码 1字节
ID01 偏移01
ID02 偏移02
....
ID0n 偏移0n
数据块

别人都叫我老木 发表于 2019-7-6 09:33

又让我想起了绝地求生

heham 发表于 2020-4-18 09:04

版本: 5
数量: 1
编码: 216
ID: -5370
偏移: -838829056
大小: 838906547
Traceback (most recent call last):
File "1.py", line 127, in <module>
    main()
File "1.py", line 123, in main
    print('内容:', Binary.bytes2str(pak.data.resources['data']))
File "1.py", line 66, in bytes2str
    out += data.decode('utf-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd8 in position 8: invalid continuation byte

zerglurker 发表于 2020-4-27 18:41

heham 发表于 2020-4-18 09:04
版本: 5
数量: 1
编码: 216


试一试gbk或者gb2312等编码看看

lecibubi 发表于 2021-1-4 16:27

下载一下试试,希望可以用!

m13276965150 发表于 2021-6-11 11:17

大佬您好,我看了您发的关于雷电的那2篇文章,收获很大
我花了2天去学习您的代码,我自身是自学的python
勉强看懂了您的代码之后我有一个很尴尬的问题就是我想尝试这用一下,但是我不懂得如何实际用起来
所以很冒昧的想请教您一下,您是否有实例的代码,可不可以让我学习一下,非常感谢。我知道我这个要求有点过分,只是看了2天,我现在不会用,而且我也不知道我要在学习什么,才能用起来,所以想请教您!
页: [1]
查看完整版本: pak文件解析代码