【问题标题】:Unpack fields from IBM data file从 IBM 数据文件中解压缩字段
【发布时间】:2016-09-29 11:24:59
【问题描述】:

我有一个来自 IBM 大型机源的 EBCDIC 编码数据文件,需要对其进行解析并转换为 ASCII。我能够通过以十六进制读取每个字节来进行转换,并在 ASCII 上查找相应的匹配项。

我的问题是 EBCDIC 编码的文件有 30 个字节被打包,需要解包以获得实际值。我正在尝试使用 PHP 打包/解包函数以及 Perl 的方法,但没有找到运气。我得到的价值似乎不是我正在寻找的确切价值。我试着用 C c H h N 解压它。

假设该文件包含一个 EBCDIC 编码数据; 包字段位于位置 635-664,30 字节长 数据1 = 9 字节 数据2 = 9 字节 数据3 = 3 字节 data4 = 3 字节 数据 5 = 3 个字节 data6 = 3 个字节

PHP:

$datafile = fopen("/var/www/data/datafile", "rb"); $regebcdicdata = fread($datafile, 634); $packfields = fread($datafile, 30); $arr= unpack('c9data1/c9bdata2/c3data3/C3data4/C3data5/C3data6',$packfields); print_r($arr); 珀尔: 打开我的 $fh, '<:raw c9 c3>

更新: 已经找到了解决办法。这 30 个字节以指定的格式打包。所以我只是使用PHP解包函数解包。

用于 EBCDIC 转换。我按字节读取它,使用 bin2hex() 函数获取十六进制值,找到匹配的 ASCII 十六进制值并获取 ASCII 表示,以便用户可以使用 chr() 函数以可读格式查看它。

我在https://www.ibm.com/support/knowledgecenter/SSZJPZ_11.3.0/com.ibm.swg.im.iis.ds.parjob.adref.doc/topics/r_deeadvrf_ASCII_and_EBCDIC_Conversion_Tables.html使用了转换表。

【问题讨论】:

  • 你需要包含数据,否则没有人可以为你尝试。您还应该包括您已经尝试过的实际代码。 Edit 问题并添加。
  • 出于保密原因,我无法包含这些数据。不过,我可以给你我在 Perl 和 PHP 中都使用过的代码。

标签: perl unpack ebcdic


【解决方案1】:

我不可能在不知道它们是如何打包的情况下帮助您解压这 30 个字节。你肯定有什么想法吧?

对于常规的EBCDIC文本,你需要确定你的文档使用的是哪个code page,然后你可以简单地使用Perl IO来解码它

假设你正在处理code page 37,那么你可以这样打开你的文件

open my $fh, '<:encoding(cp37)', 'ebcdic_file' or die $!

然后您就可以正常读取数据了。它将被检索为 Unicode 字符

【讨论】:

  • 太棒了!谢谢。所以我需要检查他们是如何打包这些数据的。我用我使用的代码编辑了我的帖子。我做对了吗?
  • @user3472277 Borodin 的意思是如果你知道数据是什么就不需要unpack,因为它们并没有真正打包,它们只是有奇怪的编码。找出它是什么编码,Perl 可以自动为你读取。
  • @simbabque:从 OP 的代码看来,有 634 个字节的 EBCDIC 编码字符,然后是 30 个字节的其他字符。这是否真的包装好我无法判断。
  • @simbabque 是的,我明白了!但我的客户说,在 635-664 位置,即 30 个字节。这些是打包的,需要解包才能获得它们的实际值。请参考我的帖子。我已经编辑过了。谢谢 :) 预期的实际值是数字格式。
  • @user3472277:您的 Perl 代码不寻常,但看起来基本没问题。你的 unpack 给我们打电话是错误的,但在我们找出这 30 个字节中的内容之前,我无法告诉你什么是正确的。
【解决方案2】:

这是疯狂的猜测,因为我不知道您使用的是哪个 EBCDIC 代码页,也不知道这 30 个字节是如何打包的。但它会做你想做的事的可能性很小

请尝试运行此程序并告诉我们结果

use strict;
use warnings 'all';
use feature 'say';

my @data = do {
    open my $fh, '<:encoding(cp37)', '/var/www/html/PERL/test' or die $!;
    local $/;
    my $data = <$fh>;
    unpack '@634 A9 A9 A3 A3 A3 A3', $data;
};

say for @data;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 2010-09-05
    相关资源
    最近更新 更多