2009-09-02 7 views
3

Lassen Sie uns sagen, dass ich eine binäre Datei, die wieWie kann ich ein unsigned int aus einer Binärdatei in Perl lesen?

[unsigned int(length of text)][text][unsigned int(length of text)][text][unsigned int(length of text)][text] 

Und dieses Muster für die Datei zu wiederholen immer wieder nur formatiert ist. Wie lese ich das unsigned int und drucke es aus, gefolgt von dem Textblock in Perl?

Auch dies ist eine Binärdatei und keine einfache Textdatei.

Antwort

2

Hier ist ein kleines Arbeitsbeispiel.

#!/usr/bin/perl 

use strict; 
use warnings; 

my $INT_SIZE = 2; 
my $filename = 'somefile.bin'; 

open my $fh, '<', $filename or die "Couldn't open file $filename: $!\n"; 

binmode $fh; 

while (read $fh, my $packed_length, $INT_SIZE) { 

    my $text = ''; 
    my $length = unpack 'v', $packed_length; 

    read $fh, $text, $length; 

    print $length, "\t", $text, "\n"; 
} 

ändern INT_SIZE und die Größe und endianness der Entpackoperation Vorlage entsprechen (entweder 'v' oder 'n' oder 'V' oder 'N'). Weitere Informationen finden Sie in der Hilfeseite unpack.

1

Sie müssen die unpack Funktion für die Daten verwenden. Überprüfen Sie Pack/Unpack Tutorial (aka How the System Stores Data).

Dies sollten Sie in die richtige Richtung gehen (32 Bit angenommen wird):

#!/usr/bin/perl 

use strict; 

my $strBuf = "perl rocks"; 
my $packed = pack("I Z15", length($strBuf), $strBuf); 
{ 
    open(my $binFile, '>', "test.bin") || die("Error opening file\n"); 
    binmode $binFile; 
    print $binFile $packed; 
    close $binFile; 
} 


open(my $binFile, '<', "test.bin") || die("Error opening file\n"); 
binmode $binFile; 

my $buffer; 
read($binFile, $buffer, 4); ## Read out unsigned int binary data 
my $length = unpack("I", $buffer); ## Unpack the data 

read($binFile, $buffer, $length); ## Read the length out as binary 
my $string = unpack("Z$length", $buffer); ## Unpack the string data in buffer 

print "Len: $length String: $string\n"; 
exit; 
+1

Ihr Code geht davon aus, dass ein 'unsigned int' in C 4 Byte ist, was nicht der Fall ist (wie Sie sehen). Ein besserer Ansatz, um dieses Verwechseln zu vermeiden, besteht darin, die gesamte Datei einzulesen und dann zu verarbeiten, so dass Ihr Code einwandfrei funktioniert, wenn er jemals auf einer 16-Bit-Plattform ausgeführt wird, wobei "unsigned int" zwei Byte ist. –

+0

Deshalb habe ich angegeben, dass ich 32 Bit angenommen habe. Ich stimme zu, dass das Einlesen in den Speicher eine gute und wohl eine bessere Lösung ist, aber wir wissen nicht, wie groß die Datei ist, die verarbeitet wird, oder wie viel Speicher auf dem Rechner verfügbar ist. Beide Lösungen haben Fallgruben. –

+0

Chris, wie vermeidet das Lesen der gesamten Datei im Speicher die Verwendung der falschen Ganzzahl? –

0

Zusätzlich unpack zu verwenden, als RC darauf hinweist, werden Sie mit ziemlicher Sicherheit read oder sysread verwenden möchten, Daten zu lesen aus der Datei.

+0

Er hat seine Antwort bearbeitet. –

0

Es gibt nicht wirklich genug Informationen hier, um dieses Problem vollständig zu lösen.

Benötigt wird das genaue Format des Längenfeldes und des Textfelds. Ist das int 2 Bytes, 4 Bytes oder 8 Bytes? (Alle sind möglich.) Ist es auch Little-Endian oder Big-Endian?

Anhand dieser Informationen greifen Sie dann mit der Lesefunktion auf die erste Ganzzahl zu und konvertieren sie mithilfe von Bitoperationen oder der Entpackfunktion in eine Zahl.

Das nächste Problem ist das genaue Format der Textzeichenfolge. Ist es ASCII, EBCDIC oder ein UTF-Format? Wenn Sie dies wissen, können Sie die Länge der Zeichenfolge berechnen und eine oder mehrere Leseoperationen verwenden, um die unbearbeitete Zeichenfolge zu erhalten, die Sie möglicherweise in eine besser verwaltbare Form konvertieren müssen.

Eine andere Sache - Sie müssen die Datei im Binärmodus öffnen, sonst erhalten Sie möglicherweise nicht die erwarteten Ergebnisse.

+0

Ich nehme an, es ist die Standardvorgabe seiner Plattform "unsigned int", die einen 'Entpack'-Code hat, so dass man sich auf Plattformabhängigkeiten wie diese verlassen kann. Und du könntest faul sein und einfach die ganze Datei einlesen und dann die Verarbeitung machen, sobald du sie gelesen hast. –