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

时间:2013-07-25 14:32:20

标签: perl file-io

我尝试读取二进制文件,将数据存储为十六进制值字符串,使用regular expressions修改一些十六进制值,然后将数据吐出到一个新的二进制文件中(是原版的略微修改版本。

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

以下是我在创建新文件时尝试做的事情:

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

我猜我的问题与我使用unpack有关。但我真的不确定如何将一个巨大的十六进制字符串放入一个实际上被读为十六进制而不是ASCII字符的形式。非常感谢任何建议!

上面显示的代码仅用于尝试将数据输出到新文件中。我已经拥有了我想要在$ data_str中输出的所有十六进制。因此,unpack是尝试将十六进制字符串转换为十六进制值列表。

我越来越近了。我从头开始删除了unpack,因为我的数据已经是一个十六进制的字符串。所以我只是将它拆分并放入数组中。这至少可以使文件的大小正确。但是,我的新问题是它会删除每个字节的第二部分并将其替换为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);
}

我明白了!我忘记了&#34; *&#34;在调用pack时,它会做的不仅仅是第一个角色!完成的代码如下。谢谢阿蒙!

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

1 个答案:

答案 0 :(得分:3)

这里,unpack返回单个字符串,而不是值数组。如果你想要一个十六进制字符数组(每个字符表示4位),那么你必须split得到的字符串:

my @data = split //, unpack "H*", $data;

(使用split /..\K/, $data拆分为等效字节)

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

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