java - 如何在Java中解析与cobol s9(6)v99格式的数据

Posted

技术标签:

【中文标题】java - 如何在Java中解析与cobol s9(6)v99格式的数据【英文标题】:How to parse data to and from cobol s9(6)v99 format in java 【发布时间】:2017-03-06 14:17:16 【问题描述】:

我以字符串形式从服务器发送和接收产品信息,服务器以 COBOLS s9(6)v99 格式接收和发送产品价格。我无法转换在 java 中从或到这种格式的小数。

COBOL s9(6)V99 格式示例:

0000016H 0000000

注意:目前我没有实现转换,我正在寻找解决方案

【问题讨论】:

那么您介意提供一些要解析的数据示例吗?我猜这里 99.9% 的用户从未使用过 COBOL! 见***.com/questions/3257771/… 我已经阅读了那个讨论,但它没有任何结果...... 所以,让发件人以您无需进行任何编码的格式发送它。选择对您来说方便的(在固定宽度的字段中),这是对 COBOL 程序的一个非常小的改动。 @theblitz 这不是负零。 【参考方案1】:

建议

一般

更改 Cobol。如果将 cobol 更改为s9(6)V99 sign leading,那么在 java 中处理起来会容易得多。在您的情况下,这可能不是一个选择 如果您可以获得 Cobol Copybook,请使用软件包

如果您可以获得 Cobol Copybook,为什么不使用其中一个 Cobol / Java 包

JRecord Cobol2J Legstar IBM 有这方面的软件

注意:即使您没有完整的 Cobol Copybook,您也可以为此字段设置 Cobol Copybook,并且仍然使用包。抄写本是:

   01  MY-REC.
       03 FIELD-1              PIC S9(6)V99.

你需要知道的

没有一种单一的 Cobol Zoned Decimal 格式,它因编译器而异 编码是什么。要解码Zoned Decimal,你真的需要知道

Cobol 编译器 服务器上使用的编码

在这种情况下,我猜是

在 IBM 大型机或 AS400 上运行的 IBM 编译器 美国 Ebdic (IBM037) 或类似的东西(绝对不是德国 EBCDIC (IBM273))

解释分区十进制

分区十进制:

S 表示它是有符号数;符号将是最后一位数字上的overpunched9 代表一位数 V 代表assumed 小数位

所以s9(6)V99是小数点前6位+后2位的有符号数

编码效果

服务器使用的encoding(字符集)决定了符号数字的表示方式。 对于美国(和英国),Ebcdic +0/-0 是 / ,但对于德国 Ebcdic,它们是不同的。 对于 ASCII 服务器,它又是不同的

Java 代码

ebcdic 转换代码(注意它仍然需要针对假定的十进制进行调整):

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;

设置+0/-0个字符

public static void setDefaultEbcidicCharacterset(String charset) 
    if (getHold(charset).isEbcdic) 
        byte[] b = (byte) 0xC0, (byte) 0xD0;
        String s = new String(b, charset);
        if (s.length() == 2) 
            positive0EbcdicZoned = s.charAt(0);
            negative0EbcdicZoned = s.charAt(1);
        
    


导出符号的另一种方法(用于 EBCDIC 编码)是将符号转换回原始字节:

private static final byte HIGH_NYBLE = (byte) 0xf0;
private static final byte ZONED_NEGATIVE_NYBLE_VALUE = (byte) 0xD0;

    String Sign = "";
    byte signByte = signStr.getBytes(encoding)[0];
    if (((byte) (signByte & HIGH_NYBLE)) == ZONED_NEGATIVE_NYBLE_VALUE) 
        sign = "-";
    
    byte lastDigitBytes = (byte) (signByte | HIGH_NYBLE);

ASCII 码

在这种情况下,它是 EBCDIC。对于基于 ASCII 的 cobol,它又是不同的。这是JRecord Ascii Zoned-Decimal 的通用转换类:

https://sourceforge.net/p/jrecord/code/HEAD/tree/jrecord/Source/JRecord_Common/src/net/sf/JRecord/Types/TypeFjZoned.java

注意:我是作者JRecord

【讨论】:

【参考方案2】:

据我所知,它应该相当简单。这假设(从您的示例中似乎就是这种情况)这是一个分区十进制。

首先,您需要获取号码的符号。只需检查最后一个字符。如果它是非数字,那么它是负数(假设您使用 F 格式作为正数)。 一旦你有了它,你就可以用正确的等效数字替换那个字符。

您现在有了一个数字的字符串表示形式。

现在做

Integer result = Integer.valueOf(theInputString)

然后除以 100 并重新应用符号。 您也可以在调用 valueOf 之前将符号作为“-”或“+”添加到字符串中。

【讨论】:

“使用 F 格式表示正数”并不像您想象的那么普遍。 因为我同时打字,所以比你想象的要少得多。当然,对于大多数 COBOL 系统来说,这可能是一件非常非常糟糕的事情。也表示粗制滥造。 很久没用 Cobol 编程了。尽管如此,这个想法仍然存在。 @theblitz 你能描述一下这里的“H”和“”是什么意思吗 几个链接可以比我更好地解释它:faculty.cs.niu.edu/~byrnes/csci360/notes/360dec.htmv8doc.sas.com/sashtml/lrcon/z1265705.htm

以上是关于java - 如何在Java中解析与cobol s9(6)v99格式的数据的主要内容,如果未能解决你的问题,请参考以下文章

你如何为 Cobol 字帖生成 java~jrecord 代码

多个 Cobol 子程序可以在同一个模块中吗

在 Mac OS 下设置 COBOL 编译器?

在 AS400 上通过 Java 流式传输运行时进程执行(cobol obj)的结果时出现 MalformedInputException

Cobol xml 解析出现异常

java outOfMemoryError 与 stringbuilder