web-dev-qa-db-fra.com

Comment puis-je créer un fichier binaire en Perl?

Par exemple, je veux créer un fichier appelé sample.bin et mettez un nombre, comme 255, pour que 255 soit enregistré dans le fichier en tant que petit-boutien, FF 00. Ou 3826 à F2 0E.

J'ai essayé d'utiliser binmode, comme l'a dit le perldoc.

36
domlao

La fonction Perl pack retournera des données "binaires" selon un modèle.

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

Dans l'exemple ci-dessus, le 's' lui indique de sortir un short (16 bits), et le '<' le force en mode petit-boutien.

En outre, ':raw' dans l'appel à open lui dit de mettre le descripteur de fichier en mode binaire sur les plateformes où cela compte (cela équivaut à utiliser binmode). La page de manuel PerlIO contient un peu plus d'informations sur les E/S dans différents formats.

43
Adam Batkin

Vous pouvez utiliser pack pour générer vos données binaires. Pour les structures complexes, Convert :: Binary :: C est particulièrement agréable.

CBC analyse les fichiers d'en-tête C (à partir d'un répertoire ou d'une variable de votre script). Il utilise les informations des en-têtes pour les données binaires pack ou unpack.

Bien sûr, si vous souhaitez utiliser ce module, il est utile de connaître certains C.

CBC vous donne la possibilité de spécifier l'endianness et les tailles pour vos types C, et vous pouvez même spécifier des fonctions pour convertir entre les types Perl natifs et les données dans le fichier binaire. J'ai utilisé cette fonctionnalité pour gérer l'encodage et le décodage de nombres à virgule fixe.

Pour votre exemple très basique que vous utiliseriez:

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 ne brille pas vraiment dans cet exemple, car il ne fonctionne qu'avec un seul court int. Si vous devez gérer des structures complexes qui peuvent avoir des typedefs tirés de plusieurs en-têtes C différents, vous serez très heureux d'avoir cet outil à portée de main.

Puisque vous êtes nouveau sur Perl, je vous suggère de toujours use stict et use warnings. Vous pouvez également use diagnostics pour obtenir des explications plus détaillées sur les messages d'erreur. Ce site et Perlmonks ont beaucoup de bonnes informations pour les débutants et de nombreuses personnes très intelligentes et compétentes prêtes à vous aider.

BTW, si vous décidez d'emprunter la route pack, consultez le pack tutorial , cela aide à clarifier la documentation quelque peu mystifiante du pack.

10
daotoad

Oui, utilisez binmode

Pour votre divertissement (sinon éducation) ma toute première tentative de création d'un fichier binaire comprenait binmode STDOUT et ce qui suit:

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

PAR Pitié, n'utilisez pas ce code! Cela vient d'une époque où je ne connaissais pas mieux.

On pourrait faire valoir que je ne le fais toujours pas, mais il est reproduit ici pour montrer que vous pouvez contrôler l'ordre des octets, même avec des méthodes mortes pour le cerveau, et parce que j'ai besoin de "deviner .

Une meilleure méthode serait d'utiliser pack comme Adam Batkin suggéré.

Je pense que j'ai commis l'atrocité ci-dessus en Perl 4. C'était il y a longtemps. J'aimerais pouvoir l'oublier ...

6
pavium