如何使用Java解码ascii文件中的comp 3压缩字段?

时间:2018-12-10 04:35:08

标签: java cobol

我有一个从旧系统中提取的大型主机文件。该文件以ascii格式编码。我想将其转换为comp3。 java中有没有可用的算法可以做到这一点?我也需要有关如何解压缩comp3字段的帮助。我尝试用Java代码解压缩comp3,但发现结果不正确

请参考代码以解压缩comp3字段

import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * Converts between integer and an array of bytes in IBM mainframe packed
 * decimal format. The number of bytes required to store an integer is (digits +
 * 1) / 2. For example, a 7 digit number can be stored in 4 bytes. Each pair of
 * digits is packed into the two nibbles of one byte. The last nibble contains
 * the sign, 0F for positive and 0C for negative. For example 7654321 becomes
 * 0x76 0x54 0x32 0x1F.
 **/ 


public class PackedDecimalToComp {

    public static void main(String[] args) {

        try {
            // test.unpackData(" 0x12345s");
            Path path = Paths.get("C:\\Users\\AV00499269\\Desktop\\Comp3 data file\\Comp3Test.txt");
            byte[] data = Files.readAllBytes(path);
            PackedDecimalToComp test = new PackedDecimalToComp();
            test.unpackData(data);
        } catch (Exception ex) {
            System.out.println("Exception is :" + ex.getMessage());
        }    
    }

    private static String unpackData(byte[] packedData) {
        String unpackedData = "";

        final int negativeSign = 13;
        for (int currentCharIndex = 0; currentCharIndex < packedData.length; currentCharIndex++) {
            byte firstDigit = (byte) ((packedData[currentCharIndex] >>> 4) & 0x0F);
            byte secondDigit = (byte) (packedData[currentCharIndex] & 0x0F);
            unpackedData += String.valueOf(firstDigit);
            if (currentCharIndex == (packedData.length - 1)) {
                if (secondDigit == negativeSign) {
                    unpackedData = "-" + unpackedData;
                }
            } else {
                unpackedData += String.valueOf(secondDigit);
            }
        }
        System.out.println("Unpackeddata is :" + unpackedData);

        return unpackedData;
    }    
}

1 个答案:

答案 0 :(得分:3)

您的代码中的注释不正确。带正号的打包数据在最后半个字节中具有x'A',x'C',x'E'或x'F'。大型机还具有“首选符号”的概念,即最后一个半字节中的x'C'为正,而最后一个半字节中的x'D'为负。

大型机数据通常在单个记录中同时包含文本和二进制数据,例如名称,货币金额和数量:

Hopper Grace ar% .

...应该是...

x'C8969797859940404040C799818385404040404081996C004B'

...以十六进制表示。这是代码页37,通常称为EBCDIC。

在不知道姓氏仅限于前10个字节的情况下,给定名称将其后限制在10个字节之内,货币金额在接下来的3个字节中使用十进制压缩格式(也称为二进制编码的十进制),并且在接下来的两个字节中添加数量,您将无法准确地传输数据,因为代码页转换会破坏货币金额。转换为通常在Microsoft Windows上使用的代码页1250,您最终会得到...

x'486F707065722020202047726163652020202020617225002E'

...翻译文本数据但打包数据被销毁的地方。打包的数据在最后半个字节(最后一个字节的下半部分)中不再具有有效的符号,货币量本身也已更改,数量也已更改(由于代码页转换和操作的错误,从十进制75更改为十进制11,776)大尾数作为小尾数)。

This question提供了一些可能对您有所帮助的答案。我的建议是先将所有数据转换为大型机上的文本,然后再将其传输到另一个平台。有一些擅长于此的大型机实用程序。