【问题标题】:Java mapping for cobol display and unpacked numeric fields用于 cobol 显示和未打包数字字段的 Java 映射
【发布时间】:2015-08-12 16:24:42
【问题描述】:

我对@9​​87654321@(显示格式)和S9(解压数字)类型感到困惑。我正在使用 Java 读取 DB2 存储过程的字帖输出

* 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 中读取带有正确符号的数字的正确逻辑是什么?

【问题讨论】:

  • 我希望他们在开发的早期阶段就对你进行了规范。您之前缺少一个数字,+9(9) 是 10 个字节长,一个用于 +/-,一个用于九个数字中的每一个,所以 (2,10)。这是一个数字编辑的字段(或者使用 (SEPARATE) SIGN 子句定义的字段)比嵌入式符号(S)更适合系统间通信,审核员会/应该说“您之前更改了数据你用它做什么?真的吗?”。

标签: java cobol copybook


【解决方案1】:

首先,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 将是 00000012L。

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

JRecord Conversion 中的 fromZoned 方法进行转换:

    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;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-22
    • 2022-12-21
    • 1970-01-01
    • 2013-03-14
    • 1970-01-01
    • 2021-10-09
    • 2015-09-05
    • 2021-10-13
    相关资源
    最近更新 更多