【问题标题】:How to read bytes from file [duplicate]如何从文件中读取字节[重复]
【发布时间】:2014-02-28 23:33:18
【问题描述】:

我正在尝试从 .lrf 文件中读取一些元数据的长度。 (配合LoLReplay程序使用)

没有关于这些文件的真正文档,但我已经想出了如何在 C++ 中执行此操作。由于多种原因,我正在尝试用 python 重写项目,但遇到了一个错误。

首先解释一下,.lrf 文件在文件开头立即具有以下格式的元数据:

  • 前 4 个字节是我不知道的。

  • 接下来的 4 个字节以十六进制形式存储元数据的长度,直到元数据的末尾,之后是回放的实际内容。

  • 前8个字节后的字节为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 格式编码的字符,但这些绝对只是我试图读取的字节。有没有办法将这些读取为字节?另外,当您尝试读取文件时,是否有更好的方法来跳过字节?

【问题讨论】:

  • 尝试以二进制模式打开文件:f = open(self.file,"rb")。另外,不要将其命名为file,因为它会与内置的file 类型名称冲突。
  • @PauloBu 不过好像没有这种类型了...
  • 在 Python2.7 中定义。在 Python3 中没有。但是阅读 OP 的代码,他可能正在使用 Python 3,所以请忽略我的评论 :)
  • @PauloBu 谢谢,我使用“rb”而不是“r”,现在我得到错误“TypeError:'bytes'对象不能被解释为整数”但c ++版本必须这样做一些棘手的事情,所以我已经大致了解如何解决这个问题。

标签: python file python-3.x


【解决方案1】:

在 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))

【讨论】:

  • 太棒了! int.from_bytes() 函数正是我所需要的。在 c++ 中,我不知道是否有等效函数,但我必须在 c++ 中手动执行此操作,并且在阅读您的评论之前,我将在 python 中手动执行此操作!谢谢!
【解决方案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)

【讨论】:

    【解决方案3】:

    您应该以二进制模式打开文件:open(filename, 'rb')

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-28
      • 1970-01-01
      • 2016-03-07
      • 2010-09-14
      相关资源
      最近更新 更多