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

C#生成EBCDIC格式文本文件时文件大小不符合预期的问题排查

EBCDIC文件生成长度不符问题排查与修复

问题描述

需要生成EBCDIC格式文本文件,输入参数及要求:

  • Action:字符串,长度1,值为'1'
  • Key:字符串,长度32,值为'11111111111111111111111111111111'
  • FD:字符串,长度8(儒略日期,值'2023188C'),需转换为4字节数组
  • FT:字符串,长度12(儒略时间,值'00000234625C'),需转换为6字节数组
  • Snil:字符串,长度20,全空格

预期总长度为1+32+4+6+20=63字节,但实际生成文件大小为173字节。以下为原C#代码:

public override void PreExecute()
{
    base.PreExecute();
    
    Encoding outputEncoding = Encoding.GetEncoding(37);
    
    textwriter = new StreamWriter(@"C:\script.txt", true, outputEncoding);
    
}

public override void PostExecute()
{
    textwriter.Close();
}

public override void Input0_ProcessInputRow(Input0Buffer Row)
{
    textwriter.Write(Row.SourceStatus);
    textwriter.Write(Row.HeaderRecordKey);
    SByte[] ebcdicData = new SByte[Row.FileDate.Length / 2];
    for (int i = 0; i < ebcdicData.Length; i++)
    {
        string chunk = Row.FileDate.Substring(i * 2, 2);
        ebcdicData[i] = Convert.ToSByte(chunk, 16);
        textwriter.Write(ebcdicData[i]);

    }
    
    SByte[] ebcdicData1 = new SByte[Row.FileTime.Length / 2];
    for (int i = 0; i < ebcdicData1.Length; i++)
    {
        string chunk = Row.FileTime.Substring(i * 2, 2);
        ebcdicData1[i] = Convert.ToSByte(chunk, 16);
        textwriter.Write(ebcdicData1[i]);

    }
    
    textwriter.Write(Row.Filler);
}

错误原因

  1. StreamWriter误用:StreamWriter是文本写入器,调用Write(sbyte)时,会将sbyte的数值转换为字符串(例如0xC会被转为"12"),再编码为EBCDIC字符,导致原本1字节的二进制数据被扩展为多个字节,直接造成文件长度超标。
  2. 二进制与文本数据混合处理错误:FD和FT转换后的是原始二进制字节,不能通过文本写入器处理,必须直接写入字节流。

修改方案

改用FileStream直接处理字节写入:对文本类型参数(Action、Key、Snil)用EBCDIC编码转换为字节数组后写入;对FD、FT转换得到的字节数组直接写入。

修改后的代码

private FileStream fileStream;
private Encoding ebcdicEncoding = Encoding.GetEncoding(37);

public override void PreExecute()
{
    base.PreExecute();
    // 打开文件流,指定路径、追加模式、读写权限
    fileStream = new FileStream(@"C:\script.txt", FileMode.Append, FileAccess.Write);
}

public override void PostExecute()
{
    fileStream?.Close();
}

public override void Input0_ProcessInputRow(Input0Buffer Row)
{
    // 写入Action(1字节)
    byte[] actionBytes = ebcdicEncoding.GetBytes(Row.SourceStatus);
    fileStream.Write(actionBytes, 0, actionBytes.Length);

    // 写入Key(32字节)
    byte[] keyBytes = ebcdicEncoding.GetBytes(Row.HeaderRecordKey);
    fileStream.Write(keyBytes, 0, keyBytes.Length);

    // 处理FD,转换为4字节并写入
    byte[] fdBytes = new byte[Row.FileDate.Length / 2];
    for (int i = 0; i < fdBytes.Length; i++)
    {
        string chunk = Row.FileDate.Substring(i * 2, 2);
        fdBytes[i] = Convert.ToByte(chunk, 16);
    }
    fileStream.Write(fdBytes, 0, fdBytes.Length);

    // 处理FT,转换为6字节并写入
    byte[] ftBytes = new byte[Row.FileTime.Length / 2];
    for (int i = 0; i < ftBytes.Length; i++)
    {
        string chunk = Row.FileTime.Substring(i * 2, 2);
        ftBytes[i] = Convert.ToByte(chunk, 16);
    }
    fileStream.Write(ftBytes, 0, ftBytes.Length);

    // 写入Snil(20字节全空格)
    byte[] fillerBytes = ebcdicEncoding.GetBytes(Row.Filler);
    fileStream.Write(fillerBytes, 0, fillerBytes.Length);
}

关键修改点

  • 替换StreamWriter为FileStream,直接操作字节流,避免文本转换导致的长度膨胀
  • 文本类型参数通过EBCDIC编码转为字节数组后写入,确保每个字符对应EBCDIC的1字节
  • FD、FT转换后的二进制字节数组直接写入流,保留原始字节长度
  • 使用byte而非sbyte处理二进制数据,避免符号转换问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 19:22:50