Wie zu Lesen Binärdatei in Perl
Ich habe ein Problem mit dem schreiben ein Perl-Skript zum Lesen einer binären Datei.
Mein code wie den folgenden, wobei die $file
sind Dateien im Binär-format. Ich habe versucht, die Suche durch das web und gelten in meinem code versucht, drucken Sie es aus, aber es scheint, es funktioniert nicht gut.
Derzeit druckt nur das '&&&&&&&&&&&" und ""ppppppppppp", aber was ich wirklich will ist, es kann drucken Sie jede der $line
, so dass ich tun kann, einige andere post-processing-später. Auch bin ich mir nicht ganz sicher, was die $data
ist wie ich das sehe, ist es Teil der code aus dem Beispiel im Artikel, die besagt angenommen, um ein Skalar. Ich brauche jemanden, der kann pin zeigen Sie mir, wo der Fehler geht falsch in meinem code. Unten ist das, was ich getan habe.
my $tmp = "$basedir/$key";
opendir (TEMP1, "$tmp");
my @dirs = readdir(TEMP1);
closedir(TEMP1);
foreach my $dirs (@dirs) {
next if ($dirs eq "." || $dirs eq "..");
print "---->$dirs\n";
my $d = "$basedir/$key/$dirs";
if (-d "$d") {
opendir (TEMP2, $d) || die $!;
my @files = readdir (TEMP2); # This should read binary files
closedir (TEMP2);
#my $buffer = "";
#opendir (FILE, $d) || die $!;
#binmode (FILE);
#my @files = readdir (FILE, $buffer, 169108570);
#closedir (FILE);
foreach my $file (@files) {
next if ($file eq "." || $file eq "..");
my $f = "$d/$file";
print "==>$file\n";
open FILE, $file || die $!;
binmode FILE;
foreach ($line = read (FILE, $data, 169108570)) {
print "&&&&&&&&&&&$line\n";
print "ppppppppppp$data\n";
}
close FILE;
}
}
}
Habe ich verändert mein code, damit geht es so wie unten. Jetzt kann ich Lesen $Daten. Dank J-16 SDiZ für den Hinweis dass. Ich bin versucht, die info hab ich aus dem Binär-Datei in ein array mit dem Namen "@array", thinkking zu grep die Daten aus dem array für string-welches match "p04", können aber nicht. Kann jemand Punkt, wo ist der Fehler???
my $tmp = "$basedir/$key";
opendir (TEMP1, "$tmp");
my @dirs = readdir (TEMP1);
closedir (TEMP1);
foreach my $dirs (@dirs) {
next if ($dirs eq "." || $dirs eq "..");
print "---->$dirs\n";
my $d = "$basedir/$key/$dirs";
if (-d "$d") {
opendir (TEMP2, $d) || die $!;
my @files = readdir (TEMP2); #This should read binary files
closedir (TEMP2);
foreach my $file (@files) {
next if ($file eq "." || $file eq "..");
my $f = "$d/$file";
print "==>$file\n";
open FILE, $file || die $!;
binmode FILE;
foreach ($line = read (FILE, $data, 169108570)) {
print "&&&&&&&&&&&$line\n";
print "ppppppppppp$data\n";
push @array, $data;
}
close FILE;
}
}
}
foreach $item (@array) {
#print "==>$item<==\n"; # It prints out content of binary file without the ==> and <== if I uncomment this.. weird!
if ($item =~ /p04(.*)/) {
print "=>$item<===============\n"; # It prints "=><===============" according to the number of binary file I have. This is wrong that I aspect it to print the content of each binary file instead :(
next if ($item !~ /^w+/);
open (LOG, ">log") or die $!;
#print LOG $item;
close LOG;
}
}
Wieder, ich habe meinen code wie folgt, aber es funktioniert immer noch nicht, wie es nicht in der Lage zu grep "p04" richtig, indem Sie auf die "log" - Datei. Es hat grep die ganze Datei mit binären wie dieser "@^@^@^@^G^D^@^@^@^^@p04bbhi06^@^^@^@^@^@^@^@^@^@hh^R^@^@^@^^@^@^@p04lohhj09^@^@^@^^@@" . Was ich aspecting wird es tun grep die nichts mit p04 nur wie grepping p04bbhi06 und p04lohhj09. Hier ist, wie mein code geht:-
foreach my $file (@files) {
next if ($file eq "." || $file eq "..");
my $f = "$d/$file";
print "==>$file\n";
open FILE, $f || die $!;
binmode FILE;
my @lines = <FILE>;
close FILE;
foreach $cell (@lines) {
if ($cell =~ /b12/) {
push @array, $cell;
}
}
}
#my @matches = grep /p04/, @lines;
#foreach $item (@matches) {
foreach $item (@array) {
#print "-->$item<--";
open (LOG, ">log") or die $!;
print LOG $item;
close LOG;
}
use autodie
Es gibt keine solche Sache als "binary format". Bitte etwas präziser sein. In welchem format sind die Dateien? Was für Eigenschaften haben Sie, die Sie verursachen, nennen Sie "im binären format'?
Es ist in .gds-format. Diese Datei ist in der Lage zu Lesen in Unix mit strings-Befehl. Es war reaable in meinem Perl-Skript, aber ich bin nicht in der Lage zu grep die Daten, die ich wollte (p04* hier in meinem code) .
Wie bereits angedeutet, verwenden Sie File::Find oder etwas, um Ihre Liste von Dateien. Für den rest, was willst du eigentlich? Ausgabe den gesamten Inhalt einer Datei wenn Sie eine übereinstimmung gefunden? Oder nur die Teile, die passen? Und was willst du spielen?
p04(.*)
Spiele alles von "p04" bis zum nächsten Zeilenumbruch. Sie haben dann, dass "alles" in $1
. Lassen Sie sich alle ungeschickt Verzeichnis Zeug und konzentrieren Sie sich zunächst auf das, was Sie wollen aus einer einzigen Datei. Wie groß sind die Dateien? Sie sind nur Lesen Sie die ersten 170 MB. Und Sie halten, überschreiben Sie die "log" - Datei, so enthält Sie nur das Letzte Element aus der letzten Datei.die OP unter dem "Binär-Datei" meinst wohl das Gegenteil von text-Dateien - z.B. gleiche Sache, wie in den perldoc-X-Dokumentation sehen Sie sich die
-B
Erklärung. (zitieren: -B
- Datei ist ein "Binär" - Datei (Gegenteil von-T).)
InformationsquelleAutor Grace | 2012-01-19
Du musst angemeldet sein, um einen Kommentar abzugeben.
Verwenden:
Werden die Daten in
$data
; und$line
ist die Anzahl der bytes, die gelesen wurden.Schätze ich, dass der vollständige Pfad ist in
$f
, aber Sie öffnen$file
. (In meinen Tests-auch$f
ist nicht den vollständigen Pfad, aber ich denke, man kann einige andere glue-code...)Wenn Sie nur wollen, zu gehen, alle Dateien in einem Verzeichnis, versuchen
File::DirWalk
oderFile::Find
.InformationsquelleAutor J-16 SDiZ
Ich bin nicht sicher, ob ich Sie richtig verstanden.
Wenn Sie Lesen müssen, eine binäre Datei, können Sie das gleiche tun wie für eine text-Datei:
Unter Windows müssen Sie
binmode F;
unter *nix-es funktioniert, ohne es.Wenn Sie brauchen, um herauszufinden, welche Zeilen in ein array enthält einige Wörter, die Sie verwenden können,
grep
Funktion:Erhalten Sie alle übereinstimmenden Zeilen in der new array
@matches
.BTW: ich glaube nicht, dass es eine gute Idee zu Lesen, Tonnen von binären Dateien gleichzeitig in den Speicher. Man kann in Ihnen suchen 1 von 1...
Wenn Sie brauchen, um zu finden wo das match Auftritt, können Sie eine andere standard-Funktion,
index
:Was wird $Datei zugeordnet werden? Ein array von Zeichen? Ein string? Etwas anderes?
InformationsquelleAutor Dimanoid
Ich bin mir nicht sicher, ich werde in der Lage sein, eine Antwort auf die OP-Frage genau, aber hier sind einige Hinweise, die möglicherweise im Zusammenhang. (edit: das ist der gleiche Ansatz wie die Antwort von @Dimanoid, aber mit mehr detail)
Sagen, Sie haben eine Datei, die eine Mischung von ASCII-Daten und binäre. Hier ist ein Beispiel in einem
bash
terminal:Beachten Sie, dass byte
00
(angegeben als\x00
) ist eine nicht-druckbare Zeichen (und inC
bedeutet es auch "Ende der Zeichenkette") - dabei, seine Präsenz isttester.txt
eine binäre Datei. Die Datei hat eine Größe von 13 Byte, gesehen vondu
, weil der nachfolgende\n
Hinzugefügt, indem dieecho
(wie es aus gesehen werden kannhexdump
).Nun, lasst uns sehen, was passiert, wenn wir versuchen, es zu Lesen mit
perl
's<>
Diamant-operator (siehe auch Was ist der nutzen of <> in perl?):Klar, die gesamte Datei nicht bekommen geschlürft - es brach in der Zeile, Ende
\n
(und nicht auf der binären\x00
). Das ist, weil der Diamant filehandle<FH>
Betreiber ist eigentlich die Abkürzung fürreadline
(siehe Perl Kochbuch: Kapitel 8 der Inhalt der Datei)Den gleichen link teilt, sollte man undefiniert der input record separator,
\$
(die standardmäßig eingestellt ist\n
), um zu schlürfen, die gesamte Datei. Vielleicht möchten Sie diese änderung nur lokal, das ist der Grund, warum die geschweiften Klammern undlocal
anstelle vonundef
(siehe Perl Redewendungen Erklärt - my $string = do { local $/; };); wir haben also:... und jetzt können wir sehen, die Datei schlürfte in seiner Gesamtheit.
Da binäre Daten impliziert nicht druckbaren Zeichen können Sie wollen, um zu überprüfen, die eigentlichen Inhalte der
$data
durch das drucken übersprintf
oderpack
/unpack
statt.Hoffe, dies hilft jemand,
Prost!
InformationsquelleAutor sdaau