Как записать данные в указанном формате в двоичный файл с Perl? - PullRequest
2 голосов
/ 19 августа 2010

это может быть довольно новый вопрос, но мне нужно обработать определенный текстовый файл и выгрузить его содержимое в двоичный файл, и я не знаю, как - я решил использовать Perl, но мои навыки работы с Perl довольно низкие.Я, вероятно, должен был написать это на C ++, но это кажется хорошей и легкой задачей для perl, так почему бы не изучить что-то новое?;) Текстовый файл имеет тысячи строк в этом формате:

2A02FC42 4

Вы можете рассматривать его как шестнадцатеричное число (длина ВСЕГДА 8)и обычный номер.Теперь мне нужно выгрузить все строки в двоичный файл в этом формате (он должен выглядеть так при просмотре в шестнадцатеричном редакторе):

42FC022A00000004

Больше примеров, чтобы было понятно:

70726F67 36 -> 676F7270000000246A656374 471 -> 7463656A000001D7

Часть анализа входного файла проста, но я застрял во второй части, где я должен записать это в двоичный файл.Я понятия не имею, как форматировать данные таким образом или даже как выводить данные в двоичном режиме.Может кто-нибудь помочь мне здесь?

Спасибо.

РЕДАКТИРОВАТЬ: обновил примеры, забыл про endiannes-im в системе LE.

Ответы [ 3 ]

6 голосов
/ 19 августа 2010

Использование 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
1 голос
/ 19 августа 2010

Моя версия (проверено):

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
0 голосов
/ 19 августа 2010

Каноническим способом является использование pack. Предположим, что данные, которые вы прочитали из текстового файла, уже преобразованы в числа (включая шестнадцатеричный) и хранятся в переменных $x и $y. Тогда вы должны сделать что-то вроде

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

Если вам нужен другой метеор, вам придется использовать шаблон отличается от NN, подробности см. perldoc -f pack.

...