2010-08-19 362 views
2

这可能是一个相当新手的问题,但我需要处理一个特定的文本文件并将其内容转储到一个二进制文件,我不知道如何 - 我决定使用Perl,但我的Perl技能很低。我可能应该用C++写这篇文章,但是这看起来对于perl来说是一个很好而且容易的任务,所以为什么不学一些新的东西呢? ;)的文本文件有上千行的格式如下:如何使用Perl将指定格式的数据写入二进制文件?

2A02FC42 4

你可以把它看作是一个十六进制数字(长度为ALWAYS 8)和常规数字。现在我需要倾倒所有的线转换成二进制文件格式(它看起来应该像这样用十六进制编辑器中查看时):

42FC022A00000004

更多的例子所以很清楚:

70726F67 36 - >676F727000000024
6A656374 471 - >7463656A000001D7

分析输入文件的部分很容易,但我被困在第二部分,我应该写成一个二进制文件这一点。我不知道如何以这种方式格式化数据,甚至不知道如何以二进制模式输出内容。有人能帮助我吗?

谢谢。

编辑:更新了例子,忘记了endiannes - 即时通讯系统。

+1

http://perldoc.perl.org/functions/pack.html – 2010-08-19 13:42:24

回答

6

使用pack

#! /usr/bin/perl 

use warnings; 
use strict; 

# demo only  
*ARGV = *DATA; 

while (<>) { 
    my($a,$b) = split; 
    $a = join "", reverse $a =~ /(..)/g; 
    $b = sprintf "%08x", $b; 

    print pack "H*" => $a . $b; 
} 

__DATA__ 
2A02FC42 4 
70726F67 36 
6A656374 471 

采样运行:

$ ./prog.pl | od -t x1 
0000000 42 fc 02 2a 00 00 00 04 67 6f 72 70 00 00 00 24 
0000020 74 63 65 6a 00 00 01 d7 
0000030
+0

谢谢,这个作品很有魅力! – PeterK 2010-08-19 14:20:21

+0

@PeterK不客气!我很高兴它有帮助。 – 2010-08-19 16:10:35

+0

注意为了获得最佳可移植性,您应该切换输出流的二进制模式:'binmode(STD0UT)' – dolmen 2010-08-20 13:43:04

0

规范的方法是使用pack。假设您从文本文件读取的数据已经转换为数字(包括十六进制数字),并存储在变量$x$y中。然后,如果你需要不同的字节顺序,你应该这样做

print OUTFILE pack("NN", $x, $y); 

,你将不得不使用 不同的模板从NN,见perldoc -f pack了解详情。

+0

尽量不要使用裸露的文件句柄; 'print $ outfile ....'更好。 – gvkv 2010-08-19 14:05:46

1

我的版本(测试):

my $fout; 
if (! open($fout, ">/tmp/deleteme.bin")) { 
    die("Failed to open /tmp/deleteme.bin: $!"); 
} 
binmode($fout); 

while (<DATA>) { 
    my ($left, $right) = split(/\s+/s, $_); 

    my $output = pack("VN", hex($left), int($right)); 
    printf(
     STDERR 
     " note, %8X %d -> " . ("%02X" x 8) . "\n", 
     hex($left), $right, 
     map { $_ } unpack("C8", $output) 
    ); 

    print($fout $output); 
} 
close($fout); 

__DATA__ 
70726F67 36 -> 676F727000000024 
6A656374 471 -> 7463656A000001D7 

输出:

note, 70726F67 36 -> 676F727000000024 
note, 6A656374 471 -> 7463656A000001D7