Как создать двоичный файл в Perl?

Например, я хочу создать файл с именем sample.bin и поместить число, например 255, так что 255 будет сохранен в файле как little-endian, FF 00. Или от 3826 до F2 0E.

Я пробовал использовать binmode, как сказал perldoc.

Ответ 1

Функция perl pack вернет "двоичные" данные в соответствии с шаблоном.

open(my $out, '>:raw', 'sample.bin') or die "Unable to open: $!";
print $out pack('s<',255) ;
close($out);

В приведенном выше примере 's' сообщает ему выводить short (16 бит), а '<' заставляет его работать в режиме little-endian.

Кроме того, ':raw' в вызове open сообщает ему, чтобы он помещал дескриптор файла в двоичный режим на платформах, где это имеет значение (эквивалентно использованию binmode). На странице руководства PerlIO содержится дополнительная информация о выполнении операций ввода-вывода в разных форматах.

Ответ 2

Вы можете использовать pack для генерации ваших двоичных данных. Для сложных структур Convert::Binary::C особенно приятно.

CBC анализирует файлы заголовков C (либо из каталога, либо из переменной в вашем script). Он использует информацию из заголовков для двоичных данных pack или unpack.

Конечно, если вы хотите использовать этот модуль, это поможет узнать некоторые C.

CBC дает вам возможность указывать континент и размеры для ваших типов C, и вы даже можете указать функции для преобразования между собственными типами Perl и данными в двоичном файле. Я использовал эту функцию для обработки кодирования и декодирования чисел с фиксированной точкой.

В вашем основном примере вы можете использовать:

use strict;
use warnings;

use IO::File; 

use Convert::Binary::C;

my $c = Convert::Binary::C->new('ByteOrder' => 'LittleEndian');

my $packed = $c->pack( 'short int', 0xFF );

print $packed;

my $fh = IO::File->new( 'outfile', '>' ) 
  or die "Unable to open outfile - $!\n";

$fh->binmode;

$fh->print( $packed );

В этом примере CBC не может сиять, поскольку он просто работает с одним коротким int. Если вам нужно обрабатывать сложные структуры, которые могут иметь typedefs, извлеченные из нескольких разных заголовков C, вы будете очень рады иметь этот инструмент под рукой.

Поскольку вы новичок в Perl, я предлагаю вам всегда use stict и use warnings. Кроме того, вы можете use diagnostics получить более подробные объяснения сообщений об ошибках. У этого сайта и Perlmonks есть много хорошей информации для начинающих и многих очень умных, опытных людей, желающих помочь вам.

Кстати, если вы решите пойти по маршруту pack, ознакомьтесь с учебником по пакету, это поможет прояснить несколько загадочную документацию пакета.

Ответ 3

Да, используйте binmode

Для вашего развлечения (если не для образования) моя первая попытка создания двоичного файла включала binmode STDOUT и следующее:

sub output_word {
    $word = $_[0];
    $lsb  = $word % 256;
    $msb  = int($word/256);
    print OUT chr($lsb) . chr($msb);
    return $word;
} 

ЗАПРЕЩАЙТЕСЬ СЕЙЧАС НЕ ИСПОЛЬЗУЙТЕ ЭТОТ КОД! Это происходит из того времени, когда я не знал ничего лучшего.

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

Лучшим методом было бы использовать pack как Адам Баткин.

Я думаю, что я совершил зверство выше в Perl 4. Это было давно. Хотел бы я забыть об этом...