代码之家  ›  专栏  ›  技术社区  ›  Sridhar

用于cobol显示和解包数字字段的Java映射

  •  1
  • Sridhar  · 技术社区  · 9 年前

    我很困惑 9 (显示格式)和 S9 (未包装的数字)类型。我正在使用 Java

    * copy book
    05 ABC PIC X(01).
    05 XYZ PIC +9(09).
    

    使用下面的Java代码,我能够正确读取这些值。数字的符号也非常清晰,可以处理 - +

    // java code 
    cobolResults.subString(1,1);
    cobolResults.subString(2,9);
    

    现在,复制本更改为提供以下未包装的数字:

    05 ABC PIC X(01).
    05 XYZ PIC S9(09).
    

    我不确定在Java中用正确的符号读取数字的正确逻辑是什么?

    1 回复  |  直到 9 年前
        1
  •  3
  •   Bruce Martin    9 年前

    首先,有来自IBM& Legstar 从Cobol Copybooks生成Java类。我自己的套餐 JRecord 也可以使用,但它面向文件而不是在线处理。

    基本上,字段的最后一个字符包含符号+数字。我猜数据来自主机;因此,对于美国-Ebcdic(CP037/IBM237),最后一位数字将是

              0 1 2 3 4 5 6 7 8 9
    positive  { A B C D E F G H I
    negative  } J K L M N O P Q R 
    

    因此,对于+123,它将是00000012C(C=+3),-123将是00000012 L。

    更糟糕的是,在不同的EBCIDIC方言和ASCII中,+0和-0是不同的。因此,您要么需要确切地知道使用的是Ebcidic的哪个版本,要么需要在字节级别进行转换。

    这个 来自分区 中的方法 JRecord Conversion 转换是否:

        private static int positiveDiff = 'A' - '1';
        private static int negativeDiff = 'J' - '1';
    
        private static char positive0EbcdicZoned = '{';
        private static char negative0EbcdicZoned = '}';
    
        public static String fromZoned(String numZoned) {
            String ret;
            String sign = "";
            char lastChar, ucLastChar;
    
            if (numZoned == null || ((ret = numZoned.trim()).length() == 0) || ret.equals("-")) {
                return "";
            }
    
            lastChar = ret.charAt(ret.length() - 1);
            ucLastChar = Character.toUpperCase(lastChar);
    
    
            switch (ucLastChar) {
            case 'A': case 'B': case 'C': 
                case 'D': case 'E': case 'F':
                case 'G': case 'H': case 'I':
                lastChar = (char) (ucLastChar - positiveDiff);
                break;
            case 'J': case 'K': case 'L':
            case 'M': case 'N': case 'O':
            case 'P': case 'Q': case 'R':
                sign = "-";
                lastChar = (char) (ucLastChar - negativeDiff);
                break;
            default:
                if (lastChar == positive0EbcdicZoned) {
                    lastChar = '0';
                } else if (lastChar == negative0EbcdicZoned) {
                    lastChar = '0';
                    sign = "-";
                }           
            }
            ret = sign + ret.substring(0, ret.length() - 1) + lastChar;
    
             return ret;
        }
    

    但在字节级别更容易实现,应该如下所示(代码未经测试):

        private static final byte HIGH_NYBLE = (byte) 0xf0;
        private static final byte LOW_NYBLE  = (byte) 0x0f;
        private static final byte ZONED_POSITIVE_NYBLE_OR = (byte) 0xCF;
        private static final byte ZONED_NEGATIVE_NYBLE_OR = (byte) 0xDF;
        private static final byte ZONED_NEGATIVE_NYBLE_VALUE = (byte) 0xD0;                        
    
        signByte = bytes[bytes.length - 1];
    
        negative = false;
        if (((byte) (signByte & HIGH_NYBLE)) == ZONED_NEGATIVE_NYBLE_VALUE) {
            negative = true;
        }
    
        long result = 0;
        for (int i = 0; i < bytes.length; i++) {
            result = result * 10 + (bytes[i] & LOW_NYBLE);
        }
    
        if (negative) {
           result = -1 * result;
        }