Python 读取包含32位浮点的二进制文件的特定部分

Python 读取包含32位浮点的二进制文件的特定部分,python,python-3.x,file-io,Python,Python 3.x,File Io,我有一个包含32位浮点的二进制文件。我需要能够将文件的某些部分读入列表或其他类似数组的结构。换句话说,我需要在数据结构中一次读取特定数量的字节(特定数量的float32s),然后使用seek()查找文件中的另一个点,然后再次执行相同的操作 在伪代码中: new_list = [] with open('my_file.data', 'rb') as file_in: for idx, offset in enumerate(offset_values): # seek

我有一个包含32位浮点的二进制文件。我需要能够将文件的某些部分读入
列表
或其他类似数组的结构。换句话说,我需要在数据结构中一次读取特定数量的字节(特定数量的
float32
s),然后使用
seek()
查找文件中的另一个点,然后再次执行相同的操作

在伪代码中:

new_list = []

with open('my_file.data', 'rb') as file_in:
    for idx, offset in enumerate(offset_values):
        # seek in the file by the offset
        # read n float32 values into new_list[idx][:]

最有效/最容易混淆的方法是什么?

输入文件中的二进制信息可以很容易地映射到虚拟内存,如果需要,可以将缓冲区导入numpy数组。一个注意事项-numpy数据类型可能会根据32位浮点是有符号的还是无符号的(本例假定为有符号的)而变化。填充的数组将包含数字(与原始字节相反)

我用一个n=10000的随机浮点数数组进行了测试,该数组被转换为字节:

import random
import struct

a = ''
for i in range(10000):
    a += struct.pack('<f', random.uniform(0, 1000))

您可以使用以下模块将字节与32位
浮点值进行转换:

样本输出:

写入值:偏移量8处的0.0687244786128608
写入值:偏移量16处的0.34336034914481284
写入值:偏移量4处的0.03658244351244533
写入值:偏移量12处的0.9733690320097427
写入值:偏移量0处的0.31991994765615206
偏移量8处的读取值:0.06872447580099106
偏移量16处的读取值:0.3433603346347809
偏移量4处的读取值:0.03658244386315346
偏移量12处的读取值:0.9733690023422241
偏移量0处的读取值:0.3199199438095093
新列表=[0.06872447580099106,0.3433603346347809,0.03658244386315346,,
0.9733690023422241, 0.3199199438095093]

请注意,读回的值略有不同,因为Python内部使用64位
float
值,因此在将它们转换为32位然后返回的过程中,某些精度会丢失。

使用内存将文件映射为具有dtype
numpy.float32
的numpy数组。这看起来非常有希望。如果我需要一次读取多个浮点值(即,将整行值读入列表的一行),该怎么办?我是否会使用包含
struct.unpack('f',buf)[0]
for
循环来运行
struct.unpack
操作,次数与我需要的行值相同?@problem\u code:是的,您可以在
for
循环中执行此操作,但是,使用该函数执行此操作会更加有效,因为如果您为其提供适当的格式字符串(即,其中四个字符串的格式为
'4f'
),则每次调用该函数时,它都能够解包多个值。请注意,严格地说,二进制文件中没有“行”,因此要在组开头的
seek()
之后以这种方式使用它,则需要在
buf
缓冲区中读入所需的
FLOAT\u SIZE
字节数。如果我需要的值数是可变的,该怎么办?我该如何为它编写格式字符串?@problem_code:如果您知道每个偏移量处预期的32位浮点数,那么可以很容易地动态构造所需的格式字符串。
import random
import struct

a = ''
for i in range(10000):
    a += struct.pack('<f', random.uniform(0, 1000))
>>> arr = np.frombuffer(a, np.dtype('float32'), offset=0)
>>> arr[500]
634.24408
import random
import struct

FLOAT_SIZE = 4
NUM_OFFSETS = 5
filename = 'my_file.data'

# Create some random offsets.
offset_values = [i*FLOAT_SIZE for i in range(NUM_OFFSETS)]
random.shuffle(offset_values)

# Create a test file
with open(filename, 'wb') as file:
    for offset in offset_values:
        file.seek(offset)
        value = random.random()
        print('writing value:', value, 'at offset', offset)
        file.write(struct.pack('f', value))

# Read sections of file back at offset locations.

new_list = []
with open(filename, 'rb') as file:
    for offset in offset_values:
        file.seek(offset)
        buf = file.read(FLOAT_SIZE)
        value = struct.unpack('f', buf)[0]
        print('read value:', value, 'at offset', offset)
        new_list.append(value)

print('new_list =', new_list)