简体   繁体   English

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

[英]How do I output a string of hex values into a binary file in Perl?

I'm trying to read in a binary file, store the data as a string of hex values, use regular expressions to modify some hex values, and spit the data out into a new binary file (that is a slightly modified version of the original). 我正在尝试读取二进制文件,将数据存储为十六进制值的字符串,使用正则表达式修改一些十六进制值,并将数据吐出到一个新的二进制文件(这是原始的略微修改版本) )。

I can do all of those steps except for the last one. 除了最后一步,我可以做所有这些步骤。 When I open the new binary file in the hex editor, it all seems to be wrong... I want it to be exactly how my hex string is, but in the hex editor. 当我在十六进制编辑器中打开新的二进制文件时,这一切似乎都是错误的...我希望它正是我的十六进制字符串的方式,但是在十六进制编辑器中。

Here is what I'm attempting to do when creating the new file: 以下是我在创建新文件时尝试执行的操作:

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

I'm guessing my problem has to do with my use of unpack . 我猜我的问题与我使用unpack有关 But I'm not really sure how else to get a huge hex string into a form where it will actually be read as hex and not ASCII characters. 但我真的不确定如何将一个巨大的十六进制字符串放入一个实际上被读为十六进制而不是ASCII字符的形式。 Any suggestions are greatly appreciated! 任何建议都非常感谢!

The code shown above is only for trying to output the data into a new file. 上面显示的代码仅用于尝试将数据输出到新文件中。 I already have all the hex I want to output in $data_str. 我已经拥有了我想要在$ data_str中输出的所有十六进制。 So the unpack is an attempt to get the string of hex into a list of hex values. 因此,unpack是尝试将十六进制字符串转换为十六进制值列表。

I'm getting closer. 我越走越近了。 I removed the unpack from the beginning since my data is already a single string of hex. 我从头开始删除了unpack,因为我的数据已经是一个十六进制的字符串。 So I just split it and put it into the array. 所以我只是将它拆分并放入数组中。 This at least gets the size of the file correct now. 这至少可以使文件的大小正确。 However, my new problem is that it's cropping off the second part of every byte and replacing it with a 0 (when viewed in the hex editor)... But when I print, the elements of the array get the correct data. 但是,我的新问题是它正在裁剪每个字节的第二部分并将其替换为0(在十六进制编辑器中查看时)......但是当我打印时,数组的元素会获得正确的数据。 Any ideas? 有任何想法吗? New code below: 新代码如下:

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

I figured it out! 我想到了! I forgot the "*" when calling pack , so it would do more than just the first character! 我在调用pack时忘记了“*”,所以它不仅仅是第一个角色! The finished code is below. 完成的代码如下。 Thanks Amon! 谢谢阿蒙!

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

Here, the unpack returns a single string, not an array of values. 这里, unpack返回一个字符串,而不是一个值数组。 If you want to have an array of hex characters (each denoting 4 bits), then you have to split the resulting string: 如果你想要一个十六进制字符数组(每个字符表示4位),那么你必须split结果字符串:

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

(use split /..\\K/, $data to split into byte-equivalents) (使用split /..\\K/, $data分割成等效的字节)

Before printing this data to a filehandle, you also have to pack it to get the original data again. 在将此数据打印到文件句柄之前,您还必须将其pack以再次获取原始数据。 I would recommend to do this at least on 8-bit parts of the original data: 我建议至少在原始数据的8位部分执行此操作:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM