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()
注意:
1 如果你已经有pak文件了,请不要下载附件
2 pak文件结构非常简单
版本 4字节 数量 4字节 编码 1字节
ID01 偏移01
ID02 偏移02
....
ID0n 偏移0n
数据块 又让我想起了绝地求生 版本: 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 heham 发表于 2020-4-18 09:04
版本: 5
数量: 1
编码: 216
试一试gbk或者gb2312等编码看看 下载一下试试,希望可以用! 大佬您好,我看了您发的关于雷电的那2篇文章,收获很大
我花了2天去学习您的代码,我自身是自学的python
勉强看懂了您的代码之后我有一个很尴尬的问题就是我想尝试这用一下,但是我不懂得如何实际用起来
所以很冒昧的想请教您一下,您是否有实例的代码,可不可以让我学习一下,非常感谢。我知道我这个要求有点过分,只是看了2天,我现在不会用,而且我也不知道我要在学习什么,才能用起来,所以想请教您!
页:
[1]