javacobolcopybook

Need Java Code/Logic to extract COMP. field from EBCDIC file


Need java code or logic to unpack COBOL COMP. field from EBCDIC file. Please help

I have tried the below code for unpacking comp. But some value i getting is in negative. Ex. 8188 we are getting as -57348

public static String getBinary(byte[] b,int decimalPointLocation) {
    long val = 0;
    int first_byte = b[0] & 0x0F;
    for (int i = 0; i < b.length; i++) {
        int low = b[i] & 0x0F;
        int high = (b[i] >> 4) & 0x0f;
        if (low < 0)
            low *= -1;
        if (high < 0)
            high *= -1;
        if(first_byte==15){
            high = 15 -high;
            low = 15 - low;
        }
        int num = high * 16 + low;
        val = 256 * val + num;
    }
    if(first_byte == 15){
        val++;
    }
    String s = ""+val;
    while(s.length()<b.length*2){
        s="0"+s;
    }
    if(first_byte == 15){
        s="-"+s;
    }
    if (decimalPointLocation > 0) {
        s = s.substring(0,
                (s.length() - decimalPointLocation))
                + "."
                + s.substring(s.length()
                        - decimalPointLocation);
    }
    return s;
}

Solution

  • I do not use Java, but I will try to explain what is happening.

    The value 8188 is 0x1ff8 in big-endian hex. When your program is run the result is actually 8188 - 65536 = -57348. That is why you got the result you did.

    Because the input is big-endian binary, only the first bit of b[0] should be checked for a sign. What I did in C# was,

        public static String GetBinary(byte[] b, int decimalPointLocation)
        {
            long val = 0;
            if ((b[0] & 0x80) != 0)
            {
                val = -1;
            }
            for (int i = 0; i < b.Length; i++)
            {
                    val = (val << 8) + b[i];
            }
            string s = Convert.ToString(val);
            return s;
        }
    

    For byte[] b = {0x1f, 0xfc} the value returned is 8188. For byte[] b = {0xe0, 0x04} the value returned is -8188.

    While I did use similar substring manipulation to insert a decimal point for those values, you need to be aware that absolute integer values less than 100 cannot be properly formatted for two decimal places with that method.