我需要读写二进制数据,其中每个数据元素:
- 大小 = 2字节(16位)
- 编码 = 有符号2的补码
- 字节序 = 大端或小端(必须可选)
是否可以不使用任何外部模块实现?如果可以,
- 如何使用read()从二进制文件中读取此类数据到整数数组L中?
- 如何使用write()将整数数组L写入二进制文件中?
我认为你最好使用 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()
file_byteorder
参数,在输入和输出中都使用 if sys.byteorder!= file_byteorder:b.byteswap()
。 - John Machinfrom 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()
总是需要两个参数。 - Sven Marnach我发现这对于从二进制文件中读取/写入数据到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)
考虑使用
struct.unpack(byteorder + str(len(rawbytes) // 2) + "h", rawbytes)
其中,byteorder
可以根据需要选择'<'
或'>'
,打包方式也是类似的。注意:我并不声称这种方法比array
更快,但我注意到array
的方式有时需要额外的byteswap
步骤。
:
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)]
struct.unpack(byteorder + str(len(rawbytes) // 2) + "h", rawbytes)
,其中byteorder
为所需的<
或>
。注意:我并不是在声称这比array
方式更快,但我确实注意到array
方式有时需要额外的byteswap
步骤。 - John Machin