2009-12-27 6 views
1

J'ai deux fichiers binaires égaux en taille, mais pas en valeurs. J'ai utilisé unpack comme suit, mais les résultats sont bizarres.Comment décompresser des fichiers binaires avec Perl?

Quand je l'utilise « gros » fichiers binaires, les deux sorties montre une partie des résultats:

Un fichier binaire commence bien - se termine mal,

fichier binaire deuxième va mal au début.

Où pensez-vous que ce soit le point faible?

open(BIN_FILE1, "<bin_files/BINF1.bin") or die("Cannot open file for writing"); 
open(BIN_FILE2, "<bin_files/BINF2.bin") or die("Cannot open file for writing"); 
binmode(BIN_FILE1); 
binmode(BIN_FILE2); 
# N An unsigned long (32-bit) in "network" (big-endian) order. 
my @values_tmp1 = unpack("N*", <BIN_FILE1>); 
my @values_tmp2 = unpack("N*", <BIN_FILE2>); 
close (BIN_FILE1); 
close (BIN_FILE2); 
my $tmp_bin1 = @values_tmp1; 
my $tmp_bin2 = @values_tmp2; 
print "\nBIN FILE1 LENGTH: ",$tmp_bin1,"\n"; 
print "\nBIN FILE2 LENGTH: ",$tmp_bin2,"\n"; 

La sortie est:

BIN FILE1 LONGUEUR: 1203

BIN FICHIER2 LONGUEUR: 124

Les fichiers d'entrée sont les suivants:

-rw-rw-r-- 1 yodar yodar 9600 2009-12-23 19:59 BINF1.bin 
-rw-rw-r-- 1 yodar yodar 9600 2009-12-27 16:38 BINF2.bin 

Si il y a un autre moyen simple et sûr de recueillir des données de fichiers binaires dans un tableau, je serai heureux de savoir.

Répondre

9

Je suppose que vous ne lisez pas le fichier entier (l'opérateur <> essaie de lire un enregistrement, en utilisant le séparateur d'enregistrements $/qui est le retour à la ligne par défaut). Essayez de changer la lecture à quelque chose comme ceci:

{ 
    # Enable slurp mode 
    local $/; 
    my @values_tmp1 = unpack("N*", <BIN_FILE1>); 
    my @values_tmp2 = unpack("N*", <BIN_FILE2>); 
} 
+0

Oui, cela résout le problème. Merci Hastukun. – YoDar

6

Vous avez dit que vous aviez de "gros" fichiers. On dirait qu'ils ne sont pas si gros, et vont facilement dans la mémoire. Cependant, si vos fichiers sont trop volumineux pour tenir dans la mémoire en même temps, vous pouvez utiliser read ou sysread pour lire les données en morceaux.

Exemple - Lire à 4000 octets à la fois:

my $file_path = 'bin_files/BINF1.bin'; 

open my $fh, '<:encoding(raw)', $file_path 
    or die "Cannot open file '$file_path' for reading"; 

my $buffer; 
while (my $got = read($fh, $buffer, 4000)) { 

    warn "Read $got bytes from file\n." 

    my @integers = unpack "N*", $buffer; 

    do_stuff(\@integers); 

    $buffer = ''; 
} 

Utilisez un 3 arguments open avec poignées lexicales, il évite certains problèmes de sécurité et de maintenabilité. 3 arg open vous permet également de spécifier le codage de fichier dans l'indicateur de mode. De cette façon, vous n'avez pas besoin d'appeler binmode.

Questions connexes