如何在 java 中将数据解析为 cobol s9(6)v99 格式
How to parse data to and from cobol s9(6)v99 format in java
我正在以字符串形式从服务器发送和接收产品信息,服务器在 COBOLS 中接收和发送产品价格 s9(6)v99 format.I 无法在 java.
中将给定的小数与此格式相互转换
COBOL s9(6)V99 格式示例:
- 0000016H
- 0000000{
注意:目前我没有实现转换,我正在寻找解决方案
据我所知,它应该相当简单。这假设,这似乎是你的例子的情况,这是一个分区小数。
首先你需要得到号码的符号。只需检查最后一个字符。如果它是非数字,则它是负数(假设您对正数使用 F 格式)。
一旦你有了它,你就可以用正确的、等效的数字替换那个字符。
您现在有了数字的字符串表示形式。
现在
Integer result = Integer.valueOf(theInputString)
然后除以 100 并重新应用符号。
您也可以在调用 valueOf 之前将符号作为“-”或“+”添加到字符串中。
建议
一般
- 更改 Cobol。如果将 cobol 更改为
s9(6)V99 sign leading
,那么在 java 中处理起来会容易得多。在你的情况下,这可能不是一个选项
- 如果你能得到 Cobol Copybook 使用一个包
套餐
如果您可以获得 Cobol Copybook,为什么不使用其中一个 Cobol/Java 包
注意:即使您没有完整的 Cobol Copybook,您也可以为这个字段设置一个 Cobol Copybook,并且仍然使用一个包。字帖为:
01 MY-REC.
03 FIELD-1 PIC S9(6)V99.
你需要知道的
没有一种单一的 Cobol Zoned Decimal 格式,它因编译器而异,并且
编码是什么。要解码 Zoned Decimal
你真的需要知道
- Cobol 编译器
- 服务器上使用的编码
在这种情况下我猜是
- IBM 编译器 运行 IBM 大型机或 AS400
- 美国 Ebdic (IBM037) 或类似的东西(绝对不是德国 EBCDIC (IBM273))
解释分区小数
分区十进制:
- S表示是有符号数;最后一位数字的符号为
overpunched
。
- 9代表一个数字
- V代表一个
assumed
小数位
所以s9(6)V99
是小数点前6位+小数点后2位的有符号数
编码效果
服务器使用的encoding
(字符集)决定了符号数字的表示方式。
对于美国(和英国)Ebcdic +0/-0 是 { / }
但它们对于德语 Ebcdic 是不同的。
对于 ASCII 服务器,它又不同了[=26=]
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 Cobols
在本例中是 EBCDIC。对于基于 ASCII 的 cobols,它又有所不同。这是 Ascii Zoned-Decimal 的 JRecord 通用转换 class:
注:我是作者JRecord
我正在以字符串形式从服务器发送和接收产品信息,服务器在 COBOLS 中接收和发送产品价格 s9(6)v99 format.I 无法在 java.
中将给定的小数与此格式相互转换COBOL s9(6)V99 格式示例:
- 0000016H
- 0000000{
注意:目前我没有实现转换,我正在寻找解决方案
据我所知,它应该相当简单。这假设,这似乎是你的例子的情况,这是一个分区小数。
首先你需要得到号码的符号。只需检查最后一个字符。如果它是非数字,则它是负数(假设您对正数使用 F 格式)。 一旦你有了它,你就可以用正确的、等效的数字替换那个字符。
您现在有了数字的字符串表示形式。
现在
Integer result = Integer.valueOf(theInputString)
然后除以 100 并重新应用符号。 您也可以在调用 valueOf 之前将符号作为“-”或“+”添加到字符串中。
建议
一般
- 更改 Cobol。如果将 cobol 更改为
s9(6)V99 sign leading
,那么在 java 中处理起来会容易得多。在你的情况下,这可能不是一个选项 - 如果你能得到 Cobol Copybook 使用一个包
套餐
如果您可以获得 Cobol Copybook,为什么不使用其中一个 Cobol/Java 包
注意:即使您没有完整的 Cobol Copybook,您也可以为这个字段设置一个 Cobol Copybook,并且仍然使用一个包。字帖为:
01 MY-REC.
03 FIELD-1 PIC S9(6)V99.
你需要知道的
没有一种单一的 Cobol Zoned Decimal 格式,它因编译器而异,并且
编码是什么。要解码 Zoned Decimal
你真的需要知道
- Cobol 编译器
- 服务器上使用的编码
在这种情况下我猜是
- IBM 编译器 运行 IBM 大型机或 AS400
- 美国 Ebdic (IBM037) 或类似的东西(绝对不是德国 EBCDIC (IBM273))
解释分区小数
分区十进制:
- S表示是有符号数;最后一位数字的符号为
overpunched
。 - 9代表一个数字
- V代表一个
assumed
小数位
所以s9(6)V99
是小数点前6位+小数点后2位的有符号数
编码效果
服务器使用的encoding
(字符集)决定了符号数字的表示方式。
对于美国(和英国)Ebcdic +0/-0 是 { / }
但它们对于德语 Ebcdic 是不同的。
对于 ASCII 服务器,它又不同了[=26=]
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 Cobols
在本例中是 EBCDIC。对于基于 ASCII 的 cobols,它又有所不同。这是 Ascii Zoned-Decimal 的 JRecord 通用转换 class:
注:我是作者JRecord