【问题标题】:How to read/write binary 16-bit data in Python 2.x?如何在 Python 2.x 中读/写二进制 16 位数据?
【发布时间】:2011-02-17 15:26:10
【问题描述】:

我要读写二进制数据,其中每个元素的数据:

  • 大小 = 2 字节(16 位)
  • 编码 = 带符号的 2 的补码
  • endiannes = 大或小(必须是 可选)

是否可以不使用任何外部模块?如果是,

  1. 如何从二进制文件中读取此类数据 使用 read() 将文件放入数组 L 中 整数?
  2. 如何写入整数数组 L 使用 write() 写入二进制文件?

【问题讨论】:

  • 你看过 Python 的 struct 模块吗?
  • 我想说 struct 模块是最好的起点
  • 使用struct 会非常低效,因为您必须一个一个地解压缩这些值。
  • @Sven Marnach:你测量过吗?
  • @S.Lott:是的,在去年回答 this question 时。我不记得确切的数字了。

标签: python binary


【解决方案1】:

我认为你最好使用array 模块。它默认以系统字节顺序存储数据,但您可以使用array.byteswap()进行字节顺序之间的转换,您可以使用sys.byteorder查询系统字节顺序。示例:

# Create an array of 16-bit signed integers
a = array.array("h", range(10))
# Write to file in big endian order
if sys.byteorder == "little":
    a.byteswap()
with open("data", "wb") as f:
    a.tofile(f)
# Read from file again
b = array.array("h")
with open("data", "rb") as f:
    b.fromfile(f, 10)
if sys.byteorder == "little":
    b.byteswap()

【讨论】:

  • 更一般地说,看到 OP 实际上想要一个 file_byteorder arg,在输入和输出中都使用 if sys.byteorder != file_byteorder: b.byteswap()
  • @John:这就是我在上面写“示例”的原因:)
【解决方案2】:
from array import array
# Edit:
from sys import byteorder as system_endian # thanks, Sven!
# Sigh...
from os import stat

def read_file(filename, endian):
    count = stat(filename).st_size / 2
    with file(filename, 'rb') as f:
        result = array('h')
        result.fromfile(f, count)
        if endian != system_endian: result.byteswap()
        return result

【讨论】:

  • array.fromfile() 总是接受两个参数。
  • 呃。这完全不方便。 :(
【解决方案3】:

考虑使用

struct.unpack(byteorder + str(len(rawbytes) // 2) + "h", rawbytes)

其中byteorder'<''>'(根据需要),对于打包也是如此。注意:我并不是说这比array 方式更快,但我确实注意到array 方式有时需要额外的byteswap 步骤。

【讨论】:

  • struct 方式总是需要一个额外的unpack() 步骤。主要区别在于您最终会得到一个 Python 列表,而使用 array.fromfile() 时会得到一个数组。
【解决方案4】:

我发现这对于将二进制文件中的数据读/写到 numpy 数组中很有用:

import numpy as np

sys.argv[1] = endian # Pass endian as an argument to the program
if endian == 'big':
    precTypecode = '>'
elif endian == 'little':
    precTypecode = '<'

# Below: 'i' is for signed integer and '2' is for size of bytes. 
# Alternatively you can make this an if else statement to choose precision
precTypecode += 'i2'

im = np.fromfile(inputFilename, dtype = precTypecode) # im is now a numpy array
# Perform any operations you desire on 'im', for example switching byteorder
im.byteswap(True)
# Then write to binary file (note: there are some limitations, so refer doc)
im.tofile(outputFilename)

希望这会有所帮助。

【讨论】:

    【解决方案5】:

    按照要求,没有任何外部模块:

    with open("path/file.bin", "rb") as file:
        byte_content = file.read()
        list_16bits = [byte_content[i + 1] << 8 | byte_content[i] for i in range(0, len(byte_content), 2)]
    

    在理解列表中,我们读取每两个字节。然后,通过按位运算,我们连接这 2 个字节。这取决于写入i+1i 的位置的字节序

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-20
      • 1970-01-01
      • 1970-01-01
      • 2014-09-20
      • 2011-03-17
      • 2017-07-10
      • 2012-07-12
      • 1970-01-01
      相关资源
      最近更新 更多