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

如何逆向解析大型机COBOL固定宽度文件并导入Pandas?

大型机COBOL固定宽度文件解析及Pandas导入方案

一、先处理文件读取与编码问题

  • 已确认每行固定437字节,先以二进制模式读取,避免编码干扰,再按固定宽度拆分:
    with open('目标文件.dat', 'rb') as f:
        lines = []
        while True:
            line = f.read(437)
            if not line:
                break
            lines.append(line)
    
  • 文本字段(如日期)用cp037或cp1140解码,二进制字段(如COMP-3类型)保留字节串,后续单独解析。

二、解析COMP-3(压缩十进制)及尾符号字段

从你提供的DTD示例来看,CSTCTL_MO_YR字段为S9(5) COMP-3,物理长度3字节,带TRAILING_SIGN:

  • COMP-3字段规则:每个字节存储两位十进制数,最后一个字节的低4位表示符号(0xC=正,0xD=负,0xF=无符号)
  • 手动解析示例(比struct更直观):
    def parse_comp3(bs):
        digits = []
        sign = '+'
        # 遍历每个字节
        for idx, b in enumerate(bs):
            if idx == len(bs) - 1:
                # 最后字节:高4位是最后一位数字,低4位是符号
                digit = (b >> 4) & 0x0F
                sign_bit = b & 0x0F
                digits.append(str(digit))
                if sign_bit == 0xD:
                    sign = '-'
            else:
                # 前序字节:高低4位各存一位数字
                digits.append(str((b >> 4) & 0x0F))
                digits.append(str(b & 0x0F))
        # S9(5)对应5位数字,取前5位拼接
        num_str = ''.join(digits[:5])
        return float(f"{sign}{num_str}")
    
    # 针对DTD中CSTCTL_MO_YR字段(物理偏移69,长度3)
    sample_val = parse_comp3(lines[0][69:69+3])
    print(sample_val)
    
  • 你看到的ç是用文本编码解码二进制COMP-3字段导致的乱码,这类字段不能按文本处理,必须按压缩十进制规则解析。

三、批量导入Pandas的两种方法

方法1:自定义字段映射+逐行解析

  1. 根据DTD整理字段元数据:
    field_specs = [
        # 示例:对应DTD中的CSTCTL_MO_YR
        {
            'name': 'CSTCTL_MO_YR',
            'type': 'comp3',
            'physical_offset': 69,
            'physical_length': 3
        },
        # 添加其他文本字段示例
        {
            'name': 'file_date',
            'type': 'text',
            'physical_offset': 0,  # 替换为实际偏移
            'physical_length': 8,   # 替换为实际长度
            'encoding': 'cp037'
        }
    ]
    
  2. 解析所有行并转为DataFrame:
    import pandas as pd
    
    def parse_line(line, specs):
        row = {}
        for spec in specs:
            segment = line[spec['physical_offset']:spec['physical_offset']+spec['physical_length']]
            if spec['type'] == 'comp3':
                row[spec['name']] = parse_comp3(segment)
            elif spec['type'] == 'text':
                row[spec['name']] = segment.decode(spec['encoding']).strip()
        return row
    
    parsed_rows = [parse_line(line, field_specs) for line in lines]
    df = pd.DataFrame(parsed_rows)
    

方法2:用read_fwf结合转换器

如果多数是文本字段,仅少数为COMP-3,可先按固定宽度读取文本,再单独处理二进制字段:

# 生成字段位置列表(物理起始-结束索引)
colspecs = [(s['physical_offset'], s['physical_offset']+s['physical_length']) for s in field_specs]
col_names = [s['name'] for s in field_specs]

# 先以文本模式读取所有字段
df_raw = pd.read_fwf('目标文件.dat', colspecs=colspecs, names=col_names, header=None, encoding='cp037', dtype=str)

# 单独转换COMP-3字段
df_raw['CSTCTL_MO_YR'] = df_raw['CSTCTL_MO_YR'].apply(lambda x: parse_comp3(x.encode('cp037')))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 07:07:48