【问题标题】:Unable to unpack comp 3 to numeric in java无法在java中将comp 3解压缩为数字
【发布时间】:2019-05-07 18:40:38
【问题描述】:

我在互联网上引用了一个代码来将 comp 3 解压缩为 java 中的数字。我试图将示例 comp3 文件传递​​给代码,但没有得到正确的解包数据。我得到了一些奇怪的数字。我是这个概念的新手(comp 3),所以你们能帮我解决这个问题。提前致谢

下面是我的代码


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.
 * 
 * This class is immutable. Once constructed you can extract the value as an
 * int, an array of bytes but you cannot change the value. Someone should
 * implement equals() and hashcode() to make this thing truly useful.
 */

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

我传递的 Comp3 文件有值 x019F

转换后,我得到解压后的数据为783031394

【问题讨论】:

  • unpackData 方法看起来有效;你的问题在别处。检查 RecordEditor (sourceforge.net/projects/record-editor) 中的文件以确保正确
  • @BruceMartin 当我解压 comp 3 字段值 x019F 时,我应该将解压后的数据设为 19,对吗?由于我是 comp3 的新手,我有这个疑问,你能解释一下上面代码中使用的逻辑吗?我对此不太清楚
  • 问题是你的文件中有 ascii string` x019F = x'7830313946' 十六进制。您需要将 binary 019F 放入文件中。最简单的方法就是用java程序写
  • 请注意,压缩十进制负号代码可以是 X'B' (11) 或 X'D' (13)。这两个值都被接受为压缩十进制指令的输入。同样,X‘A‘、X‘C‘、X‘E‘和X‘F‘都表示值正号代码。
  • 我在玩代码,它似乎可以按您的预期工作......您能举一个文件示例和一个无法正常工作的 hexdump 吗?

标签: java packed-decimal comp-3


【解决方案1】:

处理大型机二进制文件

你有两个选择:

  • 在主机上将文件转换为文本文件,然后传输文件
  • 进行二进制传输并将文件保存为 EBCDIC,然后使用 JRecord 之类的工具读取文件。您也可以使用 RecordEditor 来编辑文件

我还看到文件转换为大型机上的 Unix EBCDIC 文本文件和二进制传输(保留为 EBCDIC)。这适用于具有特殊语言特定字符的非英语 EBCDIC。 Java 编辑器(例如 JEdit)编辑 Unix Ebcdic 文件没有问题

文件传输(大型机)

将 二进制 文件(具有 comp、comp-3 等)从 Mainframe 传输到 Windows / *nix box 你必须进行Binary Transfer,原因很简单:Ebcdic --> Ascii 程序无法区分二进制字段和文本字段。

Comp-3 value   hex     hex after Ascii conversion

 400          x'400c'       x'200c'       x'40' is the ebcdic space character
                                          it gets converted to the ascii
                                          space character x'20'

您需要从大型机进行二进制传输。这会将文件保留为 EBCDIC,并且任何二进制字段都将保持不变。然后,您使用 Ebcdic 读取该文件。

您将需要检查大型机上的 RECFM。如果 RECFM 是

  • FB - 转行没问题
  • VB - 在大型机上转换为 FB 或在文件传输中包含 RDW (Record Descriptor Word) 选项。
  • 其他 - 在大型机上转换为 FB/VB

记录编辑器

  • 确保您已安装 Java
  • 您可以从here 获取RecordEditor。您可以下载安装程序或 USB 版本。 USB 版本是一个压缩目录,您可以将其安装在任何普通目录中。

使用记录编辑器

您需要定义记录布局(或文件架构)。最简单的方法是导入 Cobol Copybook。

对于一个 2 字节的 comp-3 字段,使用

创建一个 cobol 字帖
        01  Tst-Record.
            03  comp3-field              pic s9(3) comp-3.

要导入 cobol Copybook 选择 Record Layouts >>> 加载 Cobol Copybook

然后输入Cobol字帖文件名并按下屏幕底部的加载Cobol按钮

接下来进入文件打开屏幕并输入文件名并选择刚刚导入的字帖:

回车,你应该可以更新文件了:

生成代码

RecordEditor 还可以为JRecord Library 生成代码。请参阅How do you generate java~jrecord code for a Cobol copybook 了解如何使用 Cobol Copybook 生成 Java~JRecord 代码。

您还可以在编辑文件时生成不使用 Cobol Copybook 的代码:

选择Generate >>> Generate Code from the File选项。然后选择一个模板并输入一个包Id

【讨论】:

  • 谢谢@Bruce Martin 我会试试这个并回复你
  • 我有一个疑问。我有一个 ebcdic 格式的大型机文件。要将其转换为数字,我是否必须将 ebcdic 文件转换为二进制文件。因为我看不懂文件。它对我来说完全是希腊语和拉丁语
  • 二进制我的意思是没有翻译保持在大型机ebcdic格式
  • 文件看起来像这样 " Áöðöóóððùõøùõõ" " ,如何将其转换为数字。我没有二进制格式的大型机文件。希望你理解@Bruce Martin
  • 如果您有任何进一步的方法,请与我分享@Bruce Martin
【解决方案2】:

您可以使用免费工具IBM Record Generator for Java。

这允许您生成一个表示 COBOL 或 PL/I DSECT 的 Java 类,然后您可以在自己的代码中使用它来读取/写入大多数 COBOL 和 PL/I 数据类型的值。如果您不使用结构,那么您可以通过代码了解底层 JZOS 类是如何与数据类型进行交互的。

虽然该工具是免费的,但它受到 IBM 的支持,因此如果您遇到问题,可以向 IBM 提出问题,他们会解决问题。

【讨论】:

  • 谢谢。我会试试这个@Will Yates
  • 我有一个疑问。我有一个 ebcdic 格式的大型机文件。要将其转换为数字,我是否必须将 ebcdic 文件转换为二进制文件。因为我看不懂文件。它对我来说完全是希腊语和拉丁语
猜你喜欢
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 2011-01-22
  • 2015-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多