|
Binär-Dateien können Bytes mit beliebigen Werten (0..255) enthalten,
nicht nur lesbare Zeichen wie Text-Dateien. Typische Binär-Dateien sind Grafik-, Video- und Sound-Dateien, z.B. *.gif, *.jpeg, *.mp3 usw. |
Auf dieser Seite finden sie Hinweise und Beispiele zum Lesen und Schreiben von Binär-Dateien mit Perl. |
Perl
|
Scripts für CGI und Systemverwaltung |
Datei In/Out
|
Lesen und schreiben von Dateien mit Perl |
| Binär lesen | Binär-Dateien lesen und verarbeiten |
| Binär schreiben | Binär-Dateien schreiben |
| Random Access | An beliebigen Datei-Adressen Lesen oder schreiben |
| Hilfsprogramm | Dump (Hex-Ausgabe eines Binär-Strings) |
| Verwandte Themen: | |
| Text lesen | Text-Dateien lesen und verarbeiten |
| Text schreiben | Text-Dateien schreiben |
| Webseiten lesen | Live-Webseiten lesen und Informationen entnehmen |
| Perl Module | Zusatz-Module zum Lesen & Schreiben von Dateien |
| Datei-Baum | Durchforsten eines ganzen Datei-Baums (tree) |
Binär-Dateien lesen und verarbeiten |
|
|
Verwenden sie zum Test z.B. eine kleine Grafik-Datei (*.gif, *.jpg)
oder noch besser die Datei d_0_255.dat, deren Herstellung im
nächsten Kapitel demonstriert wird. ► Es ist sinnvoll, aber nicht unbedingt notwendig, vor dem Lesen die Länge der Datei festzustellen. ► Das Öffnen erfolgt mit open() genauso wie bei allen anderen Dateien. ► Unmittelbar darauf wird mit binmode verhindert, dass zufällige Byte-Kombinationen (Zeilen-Ende, Datei-Ende) das Lesen vorzeitig beenden. Dieser Befehl wird derzeit nur für Windows benötigt, schadet aber bei allen anderen Systemen nicht. ► Mit read() wird versucht, die Anzahl $soll Bytes von der Datei in die Variable $result zu lesen. Das Ergebnis $br gibt die Anzahl tatsächlich gelesener Bytes an. ► Anschließend folgt normalerweise die Verarbeitung. Das wird hier durch die Ausgabe der gelesenen Daten mit hex_dump() simuliert. Zur Decodierung (z.B. von binär codierten Ganzen Zahlen oder Gleitkomma-Zahlen) verwendet man vorteilhaft die → Funktion unpack() |
$inpath = 'c:/test/test.png';
$len1 = -s $inpath;
print "Laenge($inpath)=$len1\n";# open und binmode
$ok = open(BINREAD,$inpath);
print "open($inpath) = $ok\n";binmode BINREAD; if(!$ok) {die;} # Datei lesen
$soll = 1000;
$br =
read(BINREAD,$result,$soll);
close BINREAD;print "$br Bytes gelesen\n"; # Daten verarbeiten
hex_dump($result);
|
Lese-SchleifeFür längere Dateien oder Dateien unbekannter Länge ist diese einfache Form nicht brauchbar. In diesem Fall liest man nicht die gesamte Datei in eine Variable, sondern in einer Schleife jeweils eine bestimmte Anzahl Bytes, die meist sofort verarbeitet werden.Dabei werden normalerweise je $br=$soll Bytes von der Datei gelesen. Lediglich am Ende der Datei kann $br<$soll auftreten. |
$br = 1;
$soll = 256;
while($br) {
$br = read(BINREAD,$result,$soll);
}
# $result hier verarbeiten
|
Sequential AccessMit jedem Lese-Zugriff wird ein Zeiger (Zähler, file pointer) auf die Datei weitergesetzt. So wird gewährleistet, dass mit aufeinander folgenden Lese-Befehlen auch genau aufeinander folgende Daten gelesen werden.Eine Alternative ist der gezielte Zugriff (↓ Random Access) auf eine bestimmte Adresse der Datei. |
Ein weiteres Beispiel auf einer anderen Webseite: Verarbeitung von Text-Dateien mit → Datensätzen fixer Länge zu SQL-Anweisungen. |
Binär-Dateien schreiben |
|
|
►
Das Schreiben einer Binär-Datei unterscheidet sich nur wenig vom
Schreiben einer Text-Datei. ► In eine Binär-Datei kann man auch beliebige nicht-druckbare Zeichen schreiben. ► Im Beispiel wird eine Datei erzeugt, die 256 Bytes mit allen möglichen Werten enthält, also fortlaufend dezimal 0-255, Hex 00-FF. ► Dazu werden in einer Schleife die notwendigen Bytes im Binär-String $daten zusammengestellt: chr() erzeugt ein Byte aus dem angegebenen Wert (hier $i). ► Die Verwendung von binmode unmittelbar nach dem Öffnen der Datei stellt sicher, dass die Daten unverändert geschrieben werden (sonst wird auf Win-System jedes Zeichen 0A in die Folge 0D0A umgewandelt. ► Zur Codierung von Variablen (z.B. Ganze oder Gleitkomma-Zahlen) zu binären Daten verwendet man vorteilhaft die → Funktion pack() ► Die Daten werden mit print() in die Datei geschrieben. ► Zuletzt wird die Länge der erzeugten Datei kontrolliert. |
$outpath = 'c:/test/d_0_255.dat';
#$outpath = '/home/test/d_0_255.dat';
$daten="";
for($i=0;$i<256;$i++) {
$len3 = length($daten);
$daten.=chr($i);
}
print "Laenge(daten) = $len3\n"; # Datei Schreiben
$ok = open(BINWRITE, "> $outpath");binmode BINWRITE; print "open($outpath) = $ok\n"; print BINWRITE $result;
close BINWRITE;# Kontrolle
$len3 = -s $outpath;
print "Laenge($outpath) = $len3\n";
|
|
►
Den Inhalt der erzeugten Binärdatei können sie mit dem
Beispiel ↑
'Binärdatei Lesen' dieser Seite kontrollieren, alternativ auch mit
jedem Hex-Editor Programm. ► Bei Verzicht auf die ersten 32 (Steuer)-Zeichen ($i=32;$i<256;$i++) wird eine Text-Datei erzeugt, die man mit jedem Text-Editor lesen kann. |
► Längere Dateien werden nicht mit einer einzigen print() -Anweisung geschrieben, sondern mit print() in einer Schleife. |
Hilfs-Programme |
|
DumpDas Sub hex_dump() eignet sich zur raschen Analyse eines Binär-Strings, z.B. von Daten, die von einer Binär-Datei gelesen wurden.Typische Anwendung:
$bs = 'ABC'.chr(50).chr(51);
Das Programm gibt die Werte aller Bytes des Strings hexadezimal und - wenn möglich -
als →
ASCII-Zeichen aus, ähnlich wie mit üblichen Hex-Editoren.hex_dump($bs); Je 16 Bytes werden in einer Zeile angezeigt. Angefangene Zeilen werden mit Null-Bytes aufgefüllt. Die Ausgabe ist für die Konsole eingerichtet. Für Ausgabe auf Webseiten ersetzen sie jedes Zeichen "\n" durch "<br />\n" Es gibt keine Gewähr für die korrekte Funktion, die Anwendung erfolgt auf eigenes Risiko. |
sub hex_dump {
my ($dat)=@_;
}
my $datlen=length($dat); my($i,$j,$k,$bn)=0; my($b,$t); $t='....'; $t.=' .0 .1 .2 .3 .4 .5 .6 .7'; $t.=' .8 .9 .A .B .C .D .E .F'; $t.=' ASCII'; print "$t\n"; for($i=0;$i<$datlen;$i+=16) {
printf('%04X ',$i);
}
$t=''; for($j=0;$j<16;$j++) {
$b=substr($dat,$i+$j,1);
}$bn=ord($b); printf(' %02X',$bn); if($j==7) {print ' ';} if($bn>31 && $bn<127) {$t.=$b;} else {$t.='.';} print(" $t\n"); |
|