2010-08-19 361 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