在python中读取二进制数据

2024-10-01 07:47:38 发布

您现在位置:Python中文网/ 问答频道 /正文

首先,在这个问题被标记为重复之前,我知道其他人也问过类似的问题,但似乎没有一个明确的解释。我试图将一个二进制文件读入一个2D数组(这里有很好的文档http://nsidc.org/data/docs/daac/nsidc0051_gsfc_seaice.gd.html)。在

头是一个300字节的数组。在

到目前为止,我有

import struct

with open("nt_197912_n07_v1.1_n.bin",mode='rb') as file:
    filecontent = file.read()

x = struct.unpack("iiii",filecontent[:300])

引发字符串参数长度错误。在


Tags: 文件文档标记orghttpdocsdata二进制
1条回答
网友
1楼 · 发布于 2024-10-01 07:47:38

阅读数据(简短回答)

在从头部(见下文)确定网格的大小(n_rowsxn_cols=448x304)之后,可以简单地使用^{}读取数据。在

import numpy as np

#...

#Get data from Numpy buffer
dt = np.dtype(('>u1', (n_rows, n_cols)))
x = np.frombuffer(filecontent[300:], dt) #we know the data starts from idx 300 onwards

#Remove unnecessary dimension that numpy gave us
x = x[0,:,:]

'>u1'指定数据的格式,在本例中,无符号大小为1字节的整数,是big-endian格式。在

matplotlib.pyplot绘制此图

^{pr2}$

extent=选项只指定轴值,您可以将这些值更改为lat/lon(从头部解析)

Output

.unpack()中的错误说明

docs for ^{}

The string must contain exactly the amount of data required by the format (len(string) must equal calcsize(fmt))

您可以通过查看Format Characters部分来确定格式字符串(fmt)中指定的大小。在

您在struct.unpack("iiii",filecontent[:300])中的fmt指定了4个int类型(为了简单起见,您还可以使用4i=iiii),每个类型的大小为4,需要一个长度为16的字符串。在

您的字符串(filecontent[:300])的长度为300,而您的fmt要求的字符串长度为16,因此出现错误。在

.unpack()的用法示例

例如,在阅读您提供的文档时,我提取了前21*6字节,其格式如下:

a 21-element array of 6-byte character strings that contain information such as polar stereographic grid characteristics

有:

x = struct.unpack("6s"*21, filecontent[:126])

这将返回21个元素的元组。注意一些元素中的空白填充以满足6字节的要求。在

>> print x
    # ('00255\x00', '  304\x00', '  448\x00', '1.799\x00', '39.43\x00', '45.00\x00', '558.4\x00', '154.0\x00', '234.0\x00', '
    # SMMR\x00', '07 cn\x00', '  336\x00', ' 0000\x00', ' 0034\x00', '  364\x00', ' 0000\x00', ' 0046\x00', ' 1979\x00', '  33
    # 6\x00', '  000\x00', '00250\x00')

注意事项:

  • 第一个参数fmt"6s"*21是一个字符串,其中6s重复21 时代。每个格式字符6s代表一个6字节的字符串 (见下文),这将与您的 文件。在
  • filecontent[:126]中的数字126计算为6*21 = 126。在
  • 注意,对于s(string)说明符,前面的数字会 not表示将格式字符重复6次 通常用于其他格式字符)。相反,它指定大小 在绳子上。s表示1字节字符串,而6s表示 一个6字节的字符串。在

更广泛的标题读取解决方案(长)

因为二进制数据必须手动指定,所以在源代码中这样做可能很乏味。您可以考虑使用一些配置文件(如.ini文件)

此函数将读取头并将其存储在字典中,其中的结构是从.ini文件中给定的

# user configparser for Python 3x
import ConfigParser

def read_header(data, config_file):
    """
    Read binary data specified by a INI file which specifies the structure
    """

    with open(config_file) as fd:

        #Init the config class
        conf = ConfigParser.ConfigParser()
        conf.readfp(fd)

        #preallocate dictionary to store data
        header = {}

        #Iterate over the key-value pairs under the
        #'Structure' section
        for key in conf.options('structure'):

            #determine the string properties
            start_idx, end_idx = [int(x) for x in conf.get('structure', key).split(',')]
            start_idx -= 1 #remember python is zero indexed!
            strLength = end_idx - start_idx

            #Get the data
            header[key] = struct.unpack("%is" % strLength, data[start_idx:end_idx])

            #Format the data
            header[key] = [x.strip() for x in header[key]]
            header[key] = [x.replace('\x00', '') for x in header[key]]

        #Unmap from list-type
        #use .items() for Python 3x
        header = {k:v[0] for k, v in header.iteritems()}

    return header

下面是一个.ini文件的示例。键是存储数据时要使用的名称,值是一对逗号分隔的值,第一个是起始索引,第二个是结束索引。这些值取自您文档中的表1。

[structure]
missing_data: 1, 6
n_cols: 7, 12
n_rows: 13, 18
latitude_enclosed: 25, 30

此功能可以如下使用:

header = read_header(filecontent, 'headerStructure.ini')
n_cols = int(header['n_cols'])

相关问题 更多 >