You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解码编码未知的.dat二进制文件?

读取二进制.dat文件到Pandas的解决思路

问题背景

我需要将多个.dat二进制文件读取到Pandas中,但无法确定其编码格式。目前唯一能让Pandas不抛出异常的代码如下:

for chunk in pd.read_csv(data_file, index_col=False, sep=r'\s\s+', chunksize=10**3, engine="python"):
        print(chunk)
        break

执行后返回大量乱码:

4.2DABCDEFGHSnRbTs
0    ����@�\t�<\t��P��...
1                                        N DEN TAA
2    ��@<<J8TE�nnJ8@��N TA���`A"�UR...
3    �@DF((4PP�PP��DEZZ�PX22�PDE22u0@A�...
4                                 u0TEݠ<'Pd<��@
..                                                 ...
737                                             �PTF\
738                 pTB�(("�Pn22�pTE\�TF�
739                                    �8@F�PҨ@�
740  n�`DP��P��[`DA�x�DA�ZZ]�Td<(w...
741  "�URc,�8�A<,(TUc�ix@��m`T�...

[742 rows x 1 columns]

我读取了前三个文件的前100字节二进制数据:

with open(data_file, "rb") as f:
    data = f.read(100)
    print(data)

结果如下:

b'\x00\x034.2\x00\x01D\x00\x08ABCDEFGH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06SnRbTs\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x00\x00\x00\x00\xbb\xbb\x00\x00\x00\xf6\xca@\xd2\x0b\x00\x00\x00\x00\x00\t\xf1<\x00\x00\x00\x00\x00\t\xef\xd4\x00\x00\x00\x00\x00\x01L\x08P\x05\x0e\xe1\xf0P\xd6\xd8D'
b'\x00\x034.2\x00\x01D\x00\x08ABCDEFGH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06SnRbTs\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x00\x00\x00\x00\xbb\xbb\x00\x00\x00\xf6\xcaA\x04d\x00\x00\x00\x00\x00\x08\xea&\x00\x00\x00\x00\x00\x08\xe8\xd2\x00\x00\x00\x00\x00\x01\xd4\xc0P\x06\x0b~\xb4\x8c\x00\x1e]'
b'\x00\x034.2\x00\x01D\x00\x08ABCDEFGH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06SnRbTs\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x00\x00\x00\x00\xbb\xbb\x00\x00\x012\x81\xe1\x0b,\x00\x00\x00\x02\xad\xd9\xd9\xb0\x00\x00\x00\x02\xad\xd9\xd9\xb0\x00\x00\x00\x00\x00\x01\x86\xa0R$\nE\x00,\x8e@\x00'

我试过用chardet、charset_normalizer识别编码,也手动测试了所有Python支持的编码格式执行data.decode(enc, 'ignore'),结果全是乱码。我期望解析后的数据格式为:

datetime,ask,bid,vol
2017-01-02,134.44,134.58,89
2017-01-03,134.34,134.58,85
...

解决思路

1. 先明确:这不是文本编码问题

从二进制数据看,文件里有大量\x00空字节和非ASCII控制字符,这根本不是文本文件,所以用文本编码解码、pd.read_csv这类文本读取方法完全不适用。这类.dat文件几乎都是自定义二进制结构化格式,或者是行业/软件特定的二进制协议。

2. 先解析固定文件头

三个文件的开头完全一致,这是典型的文件头标识:

  • \x00\x03是2字节的长度前缀,对应后面的4.2(刚好3个ASCII字符)
  • \x00\x01对应后面的D(1个字符)
  • \x00\x08对应后面的ABCDEFGH(8个字符)
  • \x00\x06对应后面的SnRbTs(6个字符)
    这说明文件采用**「长度前缀+内容」**的结构化格式,字节顺序是大端(因为\x00\x03表示3,高位字节在前)。

3. 推断数据块结构并手动解析

结合你期望的datetime,ask,bid,vol结构,数据块大概率包含时间戳、两个浮点数值、一个整数。可以用Python的struct模块尝试解析:

import struct
import pandas as pd

def parse_dat_file(file_path):
    records = []
    with open(file_path, 'rb') as f:
        # 解析文件头固定字段
        len_prefix = struct.unpack('!H', f.read(2))[0]
        version = f.read(len_prefix).decode('ascii')
        
        len_prefix = struct.unpack('!H', f.read(2))[0]
        field_d = f.read(len_prefix).decode('ascii')
        
        len_prefix = struct.unpack('!H', f.read(2))[0]
        field_abc = f.read(len_prefix).decode('ascii')
        
        # 跳过连续空字节
        while True:
            b = f.read(1)
            if b != b'\x00':
                f.seek(-1, 1)
                break
        
        len_prefix = struct.unpack('!H', f.read(2))[0]
        field_sn = f.read(len_prefix).decode('ascii')
        
        # 定位到数据区(跳过\xbb\xbb前的冗余字节)
        while True:
            b = f.read(1)
            if b == b'\xbb' and f.read(1) == b'\xbb':
                break
        
        # 假设每个记录格式:8字节双精度时间戳 + 4字节单精度ask + 4字节单精度bid + 4字节无符号整数vol
        record_format = '!dffI'
        record_size = struct.calcsize(record_format)
        
        while True:
            data = f.read(record_size)
            if len(data) < record_size:
                break
            timestamp, ask, bid, vol = struct.unpack(record_format, data)
            # 转换时间戳为datetime,可根据实际调整单位
            dt = pd.to_datetime(timestamp, unit='s')
            records.append({
                'datetime': dt,
                'ask': ask,
                'bid': bid,
                'vol': vol
            })
    
    return pd.DataFrame(records)

# 测试解析
df = parse_dat_file('your_file.dat')
print(df.head())

4. 调整解析规则的技巧

  • 用二进制编辑器(如HxD、010 Editor)打开多个文件,对比相同位置的字节,找重复模式,推断记录长度和字段类型。
  • 如果解析出的数值不合理(比如时间戳对应异常日期),调整struct格式符:比如把大端!改成小端<,双精度d改成单精度f,整数类型I改成i等。
  • 若知道文件来源(如某软件导出、某接口获取),直接查对应格式文档,这是最快的方法。

5. 备选工具:用Numpy读取

如果手动解析麻烦,可尝试用numpy.fromfile读取二进制数据,再转成DataFrame:

import numpy as np
import pandas as pd

# 定义数据结构,需根据实际调整
dtype = np.dtype([
    ('timestamp', '>f8'),
    ('ask', '>f4'),
    ('bid', '>f4'),
    ('vol', '>u4')
])

# 跳过文件头长度(需根据实际计算)
data = np.fromfile('your_file.dat', dtype=dtype, offset=60)
df = pd.DataFrame(data)
df['datetime'] = pd.to_datetime(df['timestamp'], unit='s')

内容的提问来源于stack exchange,提问作者965311532

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 21:27:25