如何在Perl中将十六进制值字符串输出到二进制文件中?

如何在Perl中将十六进制值字符串输出到二进制文件中?,perl,file-io,Perl,File Io,我试图读入一个二进制文件,将数据存储为一个十六进制值字符串,用它修改一些十六进制值,然后将数据输出到一个新的二进制文件中(这是对原始文件稍加修改的版本) 除了最后一步,我可以完成所有这些步骤。当我在十六进制编辑器中打开新的二进制文件时,一切似乎都错了。。。我希望它完全是我的十六进制字符串,但在十六进制编辑器 以下是我在创建新文件时尝试执行的操作: # Format data string into an array for file processing @data_ary = unpack('

我试图读入一个二进制文件,将数据存储为一个十六进制值字符串,用它修改一些十六进制值,然后将数据输出到一个新的二进制文件中(这是对原始文件稍加修改的版本)

除了最后一步,我可以完成所有这些步骤。当我在十六进制编辑器中打开新的二进制文件时,一切似乎都错了。。。我希望它完全是我的十六进制字符串,但在十六进制编辑器

以下是我在创建新文件时尝试执行的操作:

# Format data string into an array for file processing
@data_ary = unpack('H*', $data_str);

generate_new_file($filname, \@data_ary);


sub generate_new_file
{
     my $fname = "mod -" . shift(@_);
     my $aref = shift(@_);

     open(BIN, ">", $fname) or die;
     binmode(BIN);

     for my $nybble(@$aref)
     {
         print (BIN $nybble)
     }
     close(BIN);
}
我猜我的问题与我使用。但我真的不知道如何将一个巨大的十六进制字符串转换成一种形式,在这种形式下,它实际上将被读取为十六进制而不是ASCII字符。非常感谢您的任何建议

上面显示的代码仅用于尝试将数据输出到新文件中。我已经在$data_str中输出了所有的十六进制。因此解包是试图将十六进制字符串放入十六进制值列表中

我越来越近了。我从一开始就删除了解包,因为我的数据已经是一个十六进制字符串。所以我就把它拆分,放到数组中。至少现在文件的大小是正确的。然而,我的新问题是,它正在裁剪每个字节的第二部分,并将其替换为0(在十六进制编辑器中查看时)。。。但是当我打印时,数组的元素得到了正确的数据。有什么想法吗?新代码如下:

# Format data string into an array for file processing
@data_ary = split //, $data_str;
generate_new_file($filname, \@data_ary);


sub generate_new_file
{
     my $fname = "mod -" . shift(@_);
     my $aref = shift(@_);

     open(BIN, ">", $fname) or die;
     binmode(BIN);

     for (my $i = 0; $i < @$aref; $i += 2)
     {
         my ($hi, $lo) = @$aref[$i, $i+1];
         print BIN pack "H", $hi.$lo;
     }

     close(BIN);
}
#将数据字符串格式化为数组以进行文件处理
@data_ari=split/,$data_str;
生成新文件($filname,\@data\u ari);
子生成新文件
{
my$fname=“mod-”.shift(@);
我的$aref=班次(@);
打开(BIN,“>”,$fname)或死亡;
BIN模式(BIN);
对于(我的$i=0;$i<@$aref;$i+=2)
{
我的($hi,$lo)=@$aref[$i,$i+1];
打印垃圾箱包装“H”$hi.$lo;
}
关闭(垃圾箱);
}
我知道了!我打电话时忘记了“*”,所以它不仅仅是第一个字符!完成的代码如下。谢谢阿蒙

# Format data string into an array for file processing
@data_ary = split //, $data_str;
generate_new_file($filname, \@data_ary);


sub generate_new_file
{
     my $fname = "mod -" . shift(@_);
     my $aref = shift(@_);

     open(BIN, ">", $fname) or die;
     binmode(BIN);

     for (my $i = 0; $i < @$aref; $i += 2)
     {
         my ($hi, $lo) = @$aref[$i, $i+1];
         print BIN pack "H*", $hi.$lo;
     }
     close(BIN);
}
#将数据字符串格式化为数组以进行文件处理
@data_ari=split/,$data_str;
生成新文件($filname,\@data\u ari);
子生成新文件
{
my$fname=“mod-”.shift(@);
我的$aref=班次(@);
打开(BIN,“>”,$fname)或死亡;
BIN模式(BIN);
对于(我的$i=0;$i<@$aref;$i+=2)
{
我的($hi,$lo)=@$aref[$i,$i+1];
打印箱子包装“H*”,$hi.$lo;
}
关闭(垃圾箱);
}

此处,
解包
返回单个字符串,而不是值数组。如果希望有一个十六进制字符数组(每个字符表示4位),则必须
拆分
结果字符串:

my @data = split //, unpack "H*", $data;
(使用
split/。\K/,$data
拆分为字节等价物)

在将此数据打印到文件句柄之前,您还必须对其进行
打包
以再次获取原始数据。我建议至少在原始数据的8位部分执行此操作:

for (my $i = 0; $i < @$aref; $i += 2) {
   my ($hi, $lo) = @$aref[$i, $i+1];
   print OUT pack "H*", $hi.$lo;
}
for(我的$i=0;$i<@$aref;$i+=2){
我的($hi,$lo)=@$aref[$i,$i+1];
打印出包装“H*”,$hi.$lo;
}

如果您
解包
,通常需要
打包
才能获得相同的格式。为了澄清一下,它是如何返回单个字符串的?那个解包不应该在标量上下文中,因为分配给了数组,对吗?我现在真的很困惑lol。只是尝试实现这个,我得到了一个不同的结果,但仍然不正确。结果文件的大小应该是原文件的两倍。它在十六进制编辑器中也完全混乱了。因为
H
模式创建了一个十六进制字符串,所以只返回一个值;与上下文无关。它不会创建类似于
qw/00A097/
的列表,而是
“00A097”
。当我们将这个字符串拆分为nybles(
qw/0a097/
)时,我们必须在打包之前加入它。这就是我的循环。如果我们不这样做,我们将创建一个等价的
“\x00\x00\xA0\x00\x90\x70”
,这很有意义。我越来越近了。我从一开始就删除了解包,因为我的数据已经是一个十六进制字符串。所以我就把它拆分,放到数组中。至少现在文件的大小是正确的。然而,我的新问题是,它正在裁剪每个字节的第二部分,并将其替换为0。。。有什么想法吗?很抱歉。我已经用我现在使用的代码对问题进行了编辑。这基本上是你建议的,但是没有第一次解包。我的错,只要使用模式
H*
,它应该可以正常工作。(很抱歉,没有看到您的编辑)