读取二进制文件时显示不可读字符

-1 投票
3 回答
1335 浏览
提问于 2025-04-18 17:15

这里有一个二进制文件:

ftp://n5eil01u.ecs.nsidc.org/SAN/GLAS/GLA14.034/2003.02.28/GLA14_634_1102_002_0071_0_01_0001.DAT

我尝试读取这个文件:

fname = "GLA14_634_1102_002_0071_0_01_0001.DAT"
with open (fname, 'rb') as fi:
    lines = fi.read().splitlines()
    print len(lines)    
    print lines[-1]

读取的行数是'844514',看起来是正确的。

但是最后一行显示的是一些无法识别的字符。

我该如何正确读取它呢?

3 个回答

0

你正在处理GLA14 ICESat数据记录。关于字节结构的信息,你可以在NSIDC网站上找到,链接是https://nsidc.org/data/docs/daac/glas_altimetry/gla14_records.html。至于ascii文本头,大家都说得对,它的长度是固定的。这个长度由前两行ascii文本描述(Recl=10000,表示记录的长度,Numhead=2,表示头部有两个10000字节长度的记录)。在你读取完这20000字节后,就可以开始读取GLA14的变量了。

0

这个文件看起来是一个混合了文本和二进制数据的文件。前面20000个字节是文本,后面是一些二进制数据。在文本部分似乎没有指明二进制数据的开始位置。所以我觉得这20000个字节是固定的。

你可以用下面的代码来获取文本部分:

TEXT_PART_SIZE = 20000

filename = "GLA14_634_1102_002_0071_0_01_0001.DAT"
with open(filename, 'rb') as data:
    text_lines = data.read(TEXT_PART_SIZE).strip().splitlines()

这些文本行提供了一些元数据,也许是用来解码后面的二进制数据的。没有详细的说明,我们无法读取这些二进制数据。看起来这个文件里有15个数据集和200个单独的文件打包在一起。

借助struct模块和文件格式的描述,你可以很容易地读取这样的文件。

0

这个简化示例文件的“最后一行”是从这些字节开始的:

In [49]: lines[-1][:20]
Out[49]: b'\x01\xa8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

把它转换成 int

In [50]: [int(x) for x in lines[-1][:20]]
Out[50]: [1, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

lines[-1][1] 这里,我们得到了 168,这个数字超出了 ASCII 字符的范围。

如果你想把它转换成可打印的字符,你需要找出这个文件使用了什么编码。

补充:

如果你能使用类 UNIX 系统,可以用 strings 工具(手册页)。

$ strings GLA14_634_1102_002_0071_0_01_0001.DAT | head -20
Recl=10000;
Numhead=2;
size_mb_ecs_data_granule=267.57240295410156;
time_between_contiguous_records=1;
instrument_short_name=GLAS;
platform_short_name=Icesat;
sensor_short_name=LaserAlt;
glas_osc_rate.1=1.000000028;
glas_osc_rate_date.1=2003-02-20;
glas_osc_rate_time.1=00:00:00;
sc_osc_rate.1=0.99999998864727;
sc_osc_rate_date.1=2003-02-20;
sc_osc_rate_time.1=00:00:00;
internal_time_delay.1=15.11;
internal_time_delay_date.1=2003-02-20;
internal_time_delay_time.1=00:00:00;
internal_range_delay.1=9556;
internal_range_delay_date.1=2003-02-20;
internal_range_delay_time.1=00:00:00;
ReprocessingPlanned=no further update anticipated;

撰写回答