tags:

views:

393

answers:

4

I have a value in EBCDIC format "000000{". I want to convert it into a.Net Int32 type. Can anyone let me know what I can do about it?? So my question is given a string that contains a signed numeric in EBCDIC , what should I be doing to convert it into a .NET Int32.

Thanks so much in advance!

+1  A: 

Generally speaking, you should be able to load EBCDIC data using the correct System.Text.Encoding class (the link points to a list of all encodings, which includes EBCDIC encodings). The string is then Unicode in memory and can be saved to ASCII using the ASCII encoding.

This does what you ask for in the title of the question. However, I'm not sure whether this is what you wanted to know, since your question isn't fully clear to me. If you're looking for the ASCII character code, you can just cast the character to an int as long as they are ASCII characters only.

Lucero
Your suggestion would be okay and quite correct for character data, but alas not at all good for numerical data, since it would change the numbers with the new character mapping.
ewall
@ewall, thanks for the clarification. I'm not familiar with EBCDIC itself, but I knew that there were encodings for it in the framework. That's also why I wrote the bottom paragraph about not being sure whether this actually answers the question at hand. As long as the title is left unchanged I'll leave my answer here for others which are searching for EBCDIC character conversion and come across this question, but I'll be happy to delete it when the title and question text are clearer.
Lucero
@Lucero Indeed, it is a great answer for converting between the character encodings.
ewall
A: 

Try following function..

public string ConvertEBCDICtoASCII(string strEBCDICString) {
    int[] e2a = new int[256]{
        0, 1, 2, 3,156, 9,134,127,151,141,142, 11, 12, 13, 14, 15,
        16, 17, 18, 19,157,133, 8,135, 24, 25,146,143, 28, 29, 30, 31,
        128,129,130,131,132, 10, 23, 27,136,137,138,139,140, 5, 6, 7,
        144,145, 22,147,148,149,150, 4,152,153,154,155, 20, 21,158, 26,
        32,160,161,162,163,164,165,166,167,168, 91, 46, 60, 40, 43, 33,
        38,169,170,171,172,173,174,175,176,177, 93, 36, 42, 41, 59, 94,
        45, 47,178,179,180,181,182,183,184,185,124, 44, 37, 95, 62, 63,
        186,187,188,189,190,191,192,193,194, 96, 58, 35, 64, 39, 61, 34,
        195, 97, 98, 99,100,101,102,103,104,105,196,197,198,199,200,201,
        202,106,107,108,109,110,111,112,113,114,203,204,205,206,207,208,
        209,126,115,116,117,118,119,120,121,122,210,211,212,213,214,215,
        216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,
        123, 65, 66, 67, 68, 69, 70, 71, 72, 73,232,233,234,235,236,237,
        125, 74, 75, 76, 77, 78, 79, 80, 81, 82,238,239,240,241,242,243,
        92,159, 83, 84, 85, 86, 87, 88, 89, 90,244,245,246,247,248,249,
        48, 49, 50, 51, 52, 53, 54, 55, 56, 57,250,251,252,253,254,255};

    char chrItem = Convert.ToChar("0");
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < strEBCDICString.Length; i++) {
        try {
            chrItem = Convert.ToChar(strEBCDICString.Substring(i, 1));
            sb.Append(Convert.ToChar(e2a[(int)chrItem]));
        } catch (Exception ex) {
            Console.WriteLine(ex.Message);
            return string.Empty;
        }

    }
    string result = sb.ToString();
    sb = null;
    return result;
}
Jinal Desai - LIVE
No, that won't work. If you read the question more carefully, Sai needs to get numerical data (an integer) out of the byte array. Converting it from EBDIC to ASCII would change the numbers.
ewall
+2  A: 

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);
ewall
(BTW, I'm still looking for example code in C#, since the examples I have are all in Java.)
ewall
+2  A: 

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);
        }
    }
}
Simon Chadwick