我正在尝试从.lrf文件中读取一些元数据的长度。 (与程序LoLReplay一起使用)
关于这些文件并没有真正的文档,但我已经想出如何在C ++中执行此操作。我试图在python中重新编写项目有多种原因,但我遇到了一个错误。
首先解释一下,.lrf文件以这种格式在文件的开头立即包含元数据:
前4个字节用于我不知道的事情。
接下来的4个字节以十六进制的形式存储元数据的长度,直到元数据结束,之后是重放的实际内容。
字节是json格式的元数据
我遇到的问题实际上是读取元数据长度。这是我目前的功能:
def getMetaLength(self):
try:
file = open(self.file,"r")
except IOError:
print ("Failed to open file.")
file.close()
#We need to skip the first 4 bytes.
file.read(4)
mdlength = file.read(4)
print(hex(mdlength))
file.close()
当我调用此函数时,shell返回一个回溯声明:
Traceback (most recent call last):
File "C:\Users\Donald\python\lolcogs\lolcogs_main.py", line 6, in <module>
lolcogs.getMetaLength()
File "C:\Users\Donald\python\lolcogs\LoLCogs.py", line 20, in getMetaLength
file.read(4)
File "C:\Python32\lib\encodings\cp1252.py", line 23, in decode
return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x81 in position 3648: character maps to <undefined>
我最好的猜测是read()试图读取以某种unicode格式编码的字符,但这些肯定只是我试图读取的字节。有没有办法将这些作为字节读取?此外,当您尝试读取文件时,是否有更好的方法可以跳过字节?
答案 0 :(得分:2)
在Python 3中,默认情况下使用系统编码以文本模式打开文件。您需要以二进制模式打开文件:
file = open(self.file, 'rb')
您将遇到的另一个问题是file.read(4)
将为您提供一个包含4个字节的字符串(hex
函数无法理解)。你可能想要一个整数。为此,请参阅int.from_bytes
,或者更一般地,参考struct module。然后你可以用十六进制格式打印那个数字:
mdlength = int.from_bytes(file.read(4), byteorder='big')
print(hex(mdlength))
答案 1 :(得分:2)
二进制文件应以二进制模式处理:
f = open(filename, 'rb')
对于跳过字节,我通常使用文件seek
(SEEK_CUR或SEEK_SET),或者我只是做任意file.read(n)
如果我不想打扰形式。只有我真正想要寻求的是我想跳到一个特定的位置。
解释二进制数据我只是坚持使用struct
模块提供的解包方法,这样可以很容易地定义是否要将字节序列解释为int,float,char等。这就是如何我已经做了多年,所以也许有更有效的方法,如其他答案中描述的from_bytes
方法。
使用struct模块,您可以执行
之类的操作struct.unpack("3I", f.read(12))
一次读入3个(无符号)整数。因此,举例来说,如果您采用了逆向工程的格式,我可能只会说
unk, size = struct.unpack("2I", f.read(8))
data = f.read(size)
答案 2 :(得分:1)
您应该以二进制模式打开文件:open(filename, 'rb')
。