Reputation: 188
I am sending and recieving a products information from a server as a String, the server receive and send the price of the product in COBOLS s9(6)v99 format.I am unable to convert the given decimal from or to this format in java.
COBOL s9(6)V99 format exmaples:
Note: Currently I have no implementation of the conversion,I am looking for a solution
Upvotes: 1
Views: 6073
Reputation: 3
In case its for IBM COBOL, the JZOS Record Generator with SYSADATA output from the z/OS COBOL compiler can be used to generate a Java Class representing COBOL structures and the getter and setter methods doing the conversions. Its binary (bitwise) compatible to the datatypes/structures in COBOL. It can be downloaded for free but requires an IBM ID. For compile outside z/OS the ibmjzos.jar is required, which is part of the JDK for z/OS.
Upvotes: 0
Reputation: 1
It would be much easier to have cobol in the server move the values into a screen variable like
77 S-VALUE PIC ------9,99
and export this variable which is easily readable and can be parsed into a Java double variable with:
Double value = Double.parseDouble(string);
or
Double value = new Double(string);
Upvotes: 0
Reputation: 10553
In general
s9(6)V99 sign leading
it would be a lot easier to handle in java. In your case, this is probably not an optionIf you can get the Cobol Copybook, why not use one of the Cobol / Java packages
Note: Even if you do not have the Full Cobol Copybook, you could set up a Cobol Copybook for this one field and still use a package. The copybook would be:
01 MY-REC.
03 FIELD-1 PIC S9(6)V99.
There is no one single Cobol Zoned Decimal format, it varies from compilere to Compiler and
what the encoding is. To decode Zoned Decimal
you really need to know the
In this case I would guess it is
In Zoned decimal:
overpunched
on the last numeric digit.assumed
decimal placeSo s9(6)V99
is a signed number with 6 digits before the decimal place + 2 after
The encoding
(characterset) used by the server determines how the sign digit is represented.
For US (and UK) Ebcdic +0/-0 are { / }
but they are different for German Ebcdic.
For ASCII servers it is different again
The ebcdic conversion code (note it still needs to be adjusted for the assumed decimal):
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;
}
To set +0/-0
characters
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);
}
}
}
An alternative way to derive the sign (for EBCDIC encoding) is to convert the sign back into the raw bytes:
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);
In this case it is EBCDIC. For ASCII based cobols it is different again. This is JRecord generic conversion class for Ascii Zoned-Decimal:
Note: I am the author JRecord
Upvotes: 8
Reputation: 6881
From what I can see it should be reasonably straightforward. This assumes, which seems to be the case from your example, that this is a Zoned Decimal.
First you will need to get the sign of the number. Simply check the last character. If it is a non-digit then it is negative (assuming you are using F format for the positive number). Once you have that you can then replace that character with the correct, equivalent digit.
You now have a string representation of a number.
Now do
Integer result = Integer.valueOf(theInputString)
then divide by 100 and re-apply the sign. You could also just add the sign as a "-" or "+" to the string before calling valueOf.
Upvotes: 0