读取一个压缩的十进制(Comp-3)数字值,该值是8个字符;但拥有一个13位数字并转换为13位数字值

我正在寻找代码来读取文本文件,该文本文件是在主机框架系统中创建的压缩十进制(Comp -3)数值,为8个字符,但是以压缩十进制格式保存了13位数字。

我遇到了以下代码

private Decimal Unpack(byte[] inp,int scale)
{
    long lo = 0;
    long mid = 0;
    long hi = 0;
    bool isnegative;

    // this nybble stores only the sign,not a digit.  
    // "C" hex is positive,"D" hex is negative,and "F" hex is unsigned. 
    switch (nibble(inp,0))
    {
        case 0x0D:
            isnegative = true;
            break;
        case 0x0F:
        case 0x0C:
            isnegative = false;
            break;
        default:
            throw new Exception("Bad sign nibble");
    }
    long intermediate;
    long carry;
    long digit;
    for (int j = inp.Length * 2 - 1; j > 0; j--)
    {
        // multiply by 10
        intermediate = lo * 10;
        lo = intermediate & 0xffffffff;
        carry = intermediate >> 32;
        intermediate = mid * 10 + carry;
        mid = intermediate & 0xffffffff;
        carry = intermediate >> 32;
        intermediate = hi * 10 + carry;
        hi = intermediate & 0xffffffff;
        carry = intermediate >> 32;
        // By limiting input length to 14,we ensure overflow will never occur

        digit = nibble(inp,j);
        if (digit > 9)
        {
            throw new Exception("Bad digit");
        }
        intermediate = lo + digit;
        lo = intermediate & 0xffffffff;
        carry = intermediate >> 32;
        if (carry > 0)
        {
            intermediate = mid + carry;
            mid = intermediate & 0xffffffff;
            carry = intermediate >> 32;
            if (carry > 0)
            {
                intermediate = hi + carry;
                hi = intermediate & 0xffffffff;
                carry = intermediate >> 32;
                // carry should never be non-zero. Back up with validation
            }
        }
    }
    return new Decimal((int)lo,(int)mid,(int)hi,isnegative,(byte)scale);
}

private int nibble(byte[] inp,int nibbleNo)
{
    int b = inp[inp.Length - 1 - nibbleNo / 2];
    return (nibbleNo % 2 == 0) ? (b & 0x0000000F) : (b >> 4);
}

但是上面的代码无法说出错误的标志位。

谁能确认我的阅读是否正确

 using (FileStream fs = new FileStream(pathSource,FileMode.Open))
            {
                using (StreamReader reader = new StreamReader(fs))
                {
                    List<decimal> list = new List<decimal>();

                    while (!reader.EndOfStream)
                    {
                        byte[] b = ASCIIEncoding.ASCII.GetBytes(reader.ReadLine());
                        list.Add(Unpack(b,0));
                    }

                    reader.Close();
                }
            }

注意:它不是重复的,因为我正在寻找可以读取文件并将参数传递给Unpack方法的代码。

作为参考,我添加了文件内部数据的外观:

读取一个压缩的十进制(Comp-3)数字值,该值是8个字符;但拥有一个13位数字并转换为13位数字值

zhang20090630 回答:读取一个压缩的十进制(Comp-3)数字值,该值是8个字符;但拥有一个13位数字并转换为13位数字值

“ ASCII传输类型”会将文件作为常规文本文件传输。因此,当我们以ASCII传输类型传输打包的十进制或二进制数据文件时,文件会损坏。 “二进制传输类型”将以二进制模式传输数据,该模式将文件作为二进制数据而非文本数据处理。因此,请根据您的情况使用二进制传输类型。

参考:https://www.codeproject.com/Tips/673240/EBCDIC-to-ASCII-Converter

文件准备就绪后,这是将打包的十进制转换为人类可读的十进制的代码。

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

   namespace ConsoleApp2
   {
    class Program
    {
        static void Main(string[] args)
        {
            var path = @"C:\FileName.BIN.dat";
            var templates = new List<Template>
            {
                new Template{StartPos=1,CharLength=4,Type="AlphaNum"},new Template{StartPos=5,CharLength=1,new Template{StartPos=6,CharLength=8,new Template{StartPos=14,new Template{StartPos=46,Type="Packed",DecimalPlace=2},new Template{StartPos=54,CharLength=5,DecimalPlace=0},new Template{StartPos=60,new Template{StartPos=64,Type="AlphaNum"}
            };

            var allBytes = File.ReadAllBytes(path);
            for (int i = 0; i < allBytes.Length; i += 66)
            {
                var IsLastline = (allBytes.Length - i) < 66;
                var lineLength = IsLastline ? 64 : 66;
                byte[] lineBytes = new byte[lineLength];
                Array.Copy(allBytes,i,lineBytes,lineLength);


                var outArray = new string[templates.Count];
                int index = 0;
                foreach (var temp in templates)
                {
                    byte[] amoutBytes = new byte[temp.CharLength];
                    Array.Copy(lineBytes,temp.StartPos - 1,amoutBytes,temp.CharLength);
                    var final = "";
                    if (temp.Type == "Packed")
                    {
                        final = Unpack(amoutBytes,temp.DecimalPlace).ToString();
                    }
                    else
                    {
                        final = ConvertEbcdicString(amoutBytes);
                    }

                    outArray[index] = final;
                    index++;

                }

                Console.WriteLine(string.Join(" ",outArray));

            }

            Console.ReadLine();
        }


        private static string ConvertEbcdicString(byte[] ebcdicBytes)
        {
            if (ebcdicBytes.All(p => p == 0x00 || p == 0xFF))
            {
                //Every byte is either 0x00 or 0xFF (fillers)
                return string.Empty;
            }

            Encoding ebcdicEnc = Encoding.GetEncoding("IBM037");
            string result = ebcdicEnc.GetString(ebcdicBytes); // convert EBCDIC Bytes -> 
    Unicode string
            return result;
        }

        private static Decimal Unpack(byte[] inp,int scale)
        {
            long lo = 0;
            long mid = 0;
            long hi = 0;
            bool isNegative;

            // this nybble stores only the sign,not a digit.  
            // "C" hex is positive,"D" hex is negative,AlphaNumd "F" hex is unsigned. 
            var ff = nibble(inp,0);
            switch (ff)
            {
                case 0x0D:
                    isNegative = true;
                    break;
                case 0x0F:
                case 0x0C:
                    isNegative = false;
                    break;
                default:
                    throw new Exception("Bad sign nibble");
            }
            long intermediate;
            long carry;
            long digit;
            for (int j = inp.Length * 2 - 1; j > 0; j--)
            {
                // multiply by 10
                intermediate = lo * 10;
                lo = intermediate & 0xffffffff;
                carry = intermediate >> 32;
                intermediate = mid * 10 + carry;
                mid = intermediate & 0xffffffff;
                carry = intermediate >> 32;
                intermediate = hi * 10 + carry;
                hi = intermediate & 0xffffffff;
                carry = intermediate >> 32;
                // By limiting input length to 14,we ensure overflow will never occur

                digit = nibble(inp,j);
                if (digit > 9)
                {
                    throw new Exception("Bad digit");
                }
                intermediate = lo + digit;
                lo = intermediate & 0xffffffff;
                carry = intermediate >> 32;
                if (carry > 0)
                {
                    intermediate = mid + carry;
                    mid = intermediate & 0xffffffff;
                    carry = intermediate >> 32;
                    if (carry > 0)
                    {
                        intermediate = hi + carry;
                        hi = intermediate & 0xffffffff;
                        carry = intermediate >> 32;
                        // carry should never be non-zero. Back up with validation
                    }
                }
            }
            return new Decimal((int)lo,(int)mid,(int)hi,isNegative,(byte)scale);
        }

        private static int nibble(byte[] inp,int nibbleNo)
        {
            int b = inp[inp.Length - 1 - nibbleNo / 2];
            return (nibbleNo % 2 == 0) ? (b & 0x0000000F) : (b >> 4);
        }

        class Template
        {
            public string Name { get; set; }
            public string Type { get; set; }
            public int StartPos { get; set; }
            public int CharLength { get; set; }
            public int DecimalPlace { get; set; }
        }
    }
   }
本文链接:https://www.f2er.com/3151277.html

大家都在问