
 |

Binäre Daten und Files
Als C-Programmierer kennt man die Funktionen, um in binären Files zu manövrieren. In
Perl ist es sehr ähnlich: Für Lesen gibt es read,
für Schreiben print (nein, nicht write!), für Positionieren seek und um die aktuelle Position im File zu
erhalten tell. Diese Funktionen gelten
auch für Textfiles, werden jedoch meistens in Files mit fester Recordlänge (fixed record
length) verwenden, wo beliebiger Zugriff auf einzelne Records (random access) durch
einfache Berechnungen möglich ist.
Zuerst machen wir als einfaches Beispiel die Kopie eines Files mit read und print:
open FROM, "InFile";
open TO, ">OutFile";
while (read FROM, $buf, 16384) {
print TO $buf;
}
close FROM;
close TO
open und close funktionieren wie früher besprochen.
( Es gäbe auch noch eine einfachere Möglichkeit, ein File zu kopieren: Mit dem Modul File::Copy.
)
binäre Daten
Nehmen wir an, wir hätten ein File, welches von einem C-Program geschrieben wurde und
zwar mit fester Recordlänge, dh. mit fwrite einen struct mit bekannter
Definition. Wir wollen diese Records auslesen und den Inhalt der einzelnen Felder
zugreifen. Dazu verwenden wir die Funktionen read
und unpack. unpack benötigt als Parameter ein
Template, welches die Struktur des Records (struct) beschreibt und einen String,
welcher den Record beinhaltet. Das Template ist eine Folge von Buchstaben, welche die
Reihenfolge und Art der einzelnen Felder des Records beschreibt:
- A,a ASCII String
- b,B Bit String
- h,H Hex String
- c,C Signed/Unsigned Char
- s,S Signed/Unsigned Short
- i,I Signed/Unsigned Integer
- l,L Signed/Unsigned Long
- p Pointer to a null-terminated string.
Weitere Templates sind unter der Funktion pack
zu finden.
Ein Teil des C-Codes für obiges Beispiel sieht wie folgt aus:
struct{char st[4]; int in; double d;} gaga;
fwrite(&gaga, sizeof(gaga) 1 , fp) (* FILE *fp *)
Perl-Code:
$template = "a4 i d";
$len = length pack($template,'',0,0)
read(FP,$rec,$len) # open FP, "filename";
($str,$in,$d) = unpack($template,$rec);
Mit pack kann ein Record wie in C
erzeugt werden. Wir brauchen diese Funktion hier, um die Länge des Records zu bestimmen.
Formatierte Ausgabe
Perl liefert einen Mechanismus um einfache Reports und Tabellen auszugeben, der über
die Möglichkeiten der print- und printf-Funktion hinausgeht. Man deklariert
das Layout der Ausgabe mit format und
gibt die einzelnen Records mit write aus. Die Deklaration format kann irgendwo im Programm
erfolgen und hat die folgende Syntax:
format NAME =
FORMLIST
.
NAME ist der Formatname und wird defaultmässig dem gleichnamigen Filehandle
zugeordnet. Falls er weggelassen wird, wird STDOUT angenommen.
FORMLIST besteht aus einer Folge von Zeilen, die jede entweder eine
Kommentarzeile sein kann, mit einen #-Zeichen am Anfang, eine Format-Zeile, welche das
Aussehen der Ausgabe beschreibt, oder eine Parameterzeile, welche die auszugebenden
Variablen zu der vorangehenden Format-Zeile angibt. Mit der gleichen Syntax kann das
Format für eine oder mehrere Kopfzeilen angegeben werden. Der Name von
Kopfzeilen-Formaten hat die Form FILEHANDLE_TOP, resp. für STDOUT
nur TOP. Es gibt wiederum eine Anzahl von Spezialvariablen, welche im
Zusammenhang mit Formaten gebraucht werden können. Zum Beispiel ist $~ gleich dem Namen des
aktuellen Ausgabeformates, resp. $^
derjenige, des aktuellen Kopfzeilen-Formates.
Beispiel: Wir möchten nun das binäre File, welches wir oben gelesen habe, schön
formattiert ausgeben:
format TOP =
Binaeres File
STRING INTEGER DOUBLE
----------------------------------
.
format =
# String linksbuendig, Integer zentriert, Double rechtsbuendig
@<<<< @|||||| @>>>>>
$str,$in,$d
.
while (read(FP,$rec,$len)) {
($str,$in,$d) = unpack($template,$rec);
write;
}
Für weitere Details zu Formaten, wende man sich an das Manual.
Uebung
Schreibe ein Programm, welches das File /var/adm/wtmp eines UNIX-Systemes
ausliest. Dieses File enthält die Informationen über die Logins des Systems.
Formattiere die Ausgabe mit format. Die Struktur des Files
/var/adm/wtmp ist systemabhängig. (Siehe man utmp).
|

|

|