How to convert from EBCDIC to ASCII in C#.net

Solution 1:

Try this

    #region public static byte[] ConvertAsciiToEbcdic(byte[] asciiData)
    public static byte[] ConvertAsciiToEbcdic(byte[] asciiData)     
    {          
        // Create two different encodings.         
        Encoding ascii = Encoding.ASCII;
        Encoding ebcdic = Encoding.GetEncoding("IBM037");          

        //Retutn Ebcdic Data
        return Encoding.Convert(ascii, ebcdic, asciiData);      
    }     
    #endregion      

    #region public static byte[] ConvertEbcdicToAscii(byte[] ebcdicData)
    public static byte[] ConvertEbcdicToAscii(byte[] ebcdicData)
    {         
        // Create two different encodings.      
        Encoding ascii = Encoding.ASCII;
        Encoding ebcdic = Encoding.GetEncoding("IBM037"); 

        //Retutn Ascii Data 
        return Encoding.Convert(ebcdic, ascii, ebcdicData); 
    } 
    #endregion

Solution 2:

The following program has worked for converting an EBCDIC value to an integer, when receiving data from one of our customers. The data we get may be a subset of what you might get, so see if this works for you:

using System;
using System.Text;

namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            string strAmount = "00007570{";
            Console.WriteLine("{0} is {1}", strAmount, ConvertEBCDICtoInt(strAmount));
            strAmount = "000033}";
            Console.WriteLine("{0} is {1}", strAmount, ConvertEBCDICtoInt(strAmount));
            Console.ReadLine();
        }

        // This converts "00007570{" into "75700", and "000033}" into "-330"
        public static int? ConvertEBCDICtoInt(string i_strAmount)
        {
            int? nAmount = null;

            if (string.IsNullOrEmpty(i_strAmount))
                return(nAmount);

            StringBuilder strAmount = new StringBuilder(i_strAmount);
            if (i_strAmount.IndexOfAny(new char[] { '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R' }) >= 0)
                strAmount.Insert(0, "-");

            strAmount.Replace("{", "0");
            strAmount.Replace("}", "0");
            strAmount.Replace("A", "1");
            strAmount.Replace("J", "1");
            strAmount.Replace("B", "2");
            strAmount.Replace("K", "2");
            strAmount.Replace("C", "3");
            strAmount.Replace("L", "3");
            strAmount.Replace("D", "4");
            strAmount.Replace("M", "4");
            strAmount.Replace("E", "5");
            strAmount.Replace("N", "5");
            strAmount.Replace("F", "6");
            strAmount.Replace("O", "6");
            strAmount.Replace("G", "7");
            strAmount.Replace("P", "7");
            strAmount.Replace("H", "8");
            strAmount.Replace("Q", "8");
            strAmount.Replace("I", "9");
            strAmount.Replace("R", "9");

            // Convert the amount to a int:
            int n;
            if (int.TryParse(strAmount.ToString(), out n))
                nAmount = n;
            return (nAmount);
        }
    }
}

Solution 3:

You're going to want to read up on binary-coded decimals, as that is what you are facing, and there are questions to answer before you can really code it.

If the value is a single character, it may be as simple as getting the char number--but you need to know if the system is Big Endian (like most mainframes from which you would be getting EBDIC-encoded files) or Little Endian (like more modern OSes).

If your integer value uses more than one character and includes the sign (as you mention), then it is more complex. Most likely, each half (or "nibble", or 4 bits) of each character represents the number--maybe 0 thru 9 or in hex 0 thru F, and the string is padded with zeros (nulls, actually) on the left, and the last nibble contains the sign. This system might be called Zoned Decimal in some parlance.

All in all, I would recommend starting by reading this article, which should introduce you to how data is/was stored on COBOL-based mainframes, and get you moving the right direction.


In C#, you may be able to do the conversion form the common Zoned Decimal (which sounds like the best fit for your incoming data as you have described it) by using int.Parse with the correct NumberStyles options, like this:

int val = int.Parse(num, NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite);