[英]Reading binary data in python
首先,在此问题被标记为重复之前,我知道其他人已经提出类似的问题,但似乎没有明确的解释。 我正在尝试将二进制文件读入二维数组(在此处有详细记录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])
抛出字符串参数长度的错误。
从标题中确定网格的大小( n_rows
x n_cols
= 448x304)后(见下文),您只需使用numpy.frombuffer
读取数据numpy.frombuffer
。
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
绘制它
import matplotlib.pyplot as plt
#...
plt.imshow(x, extent=[0,3,-3,3], aspect="auto")
plt.show()
extent=
选项只是指定轴值,您可以将它们更改为lat / lon(例如从头部解析)
来自struct.unpack(fmt, string)
的文档 :
字符串必须包含格式所需的数据量(
len(string)
必须等于calcsize(fmt)
)
您可以通过查看“ 格式字符”部分来确定格式字符串( fmt
)中指定的大小。
您在struct.unpack("iiii",filecontent[:300])
fmt
指定了4种int类型(为简单起见,您也可以使用4i
= iiii
),每种类型的大小为4,需要长度为16的字符串。
你的字符串( filecontent[:300]
)长度为300,而你的fmt
要求长度为16的字符串,因此错误。
例如,读取提供的文档我提取了前21 * 6个字节,其格式为:
包含6字节字符串的21个元素的数组,包含极性立体网格特征等信息
附:
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
(字符串)说明符,前面的数字并不意味着重复格式字符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'])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.