| ## Funktionen für Ein-/Ausgabe und Lesen/Schreiben von Daten
| Allgemeines zu diesen Funktionen binmode - Ein-/Ausgabekanal binär behandeln close - Ein-/Ausgabekanal schließen closedir - Verzeichnis schließen eof - auf Dateiende prüfen fileno - Nummer eines geöffneten Ein-/Ausgabekanal flock - geöffnete Datei vor Zugriffen schützen format - Daten vor dem Ausgeben formatieren getc - nächstes Zeichen lesen open - Ein-/Ausgabekanal öffnen opendir - Verzeichnis öffnen print - Daten ausgeben printf - Daten formatiert ausgeben read - bestimmte Anzahl Zeichen lesen readdir - Verzeichniseinträge ermitteln rewinddir - auf ersten Verzeichniseintrag positionieren seek - Dateizeiger positionieren seekdir - Verzeichniszeiger positionieren select - Ein-/Ausgabekanal auswählen sysopen - Datei systemnah öffnen sysread - bestimmte Anzahl Zeichen systemnah lesen sysseek - Dateizeiger systemnah positionieren syswrite - bestimmte Anzahl Zeichen systemnah schreiben tell - Position des Dateizeigers ermitteln telldir - Position des Verzeichniszeigers ermitteln write - formatierte Daten schreiben

## Allgemeines zu diesen Funktionen

Für Perl gibt es einen voreingestellten Eingabekanal `STDIN` - standard input und einen voreingestellten Ausgabekanal `STDOUT` - standard output. Ein Perl-Script kann von `STDIN` Daten lesen und auf `STDOUT` Daten ausgeben. Normalerweise ist `STDIN` mit der Tastatur verbunden, d.h. Tastatureingaben können von `STDIN` gelesen werden. `STDOUT` ist dagegen normalerweise mit dem Bildschirm verbunden, d.h. Ausgaben auf `STDOUT` erscheinen am Monitor. Bei Verwendung eines Web-Servers mit CGI-Schnittstelle wird `STDOUT` jedoch in eine spezielle Datei "umgebogen", die vom Web-Server an den Web-Browser weitergeleitet wird, und `STDIN` ebenfalls eine spezielle Datei, in der der Web-Server die Daten (z.B. Formulardaten) dem aufgerufenen CGI-Script bereitstellt.
Neben `STDOUT` gibt es auch noch einen weiteren, speziellen Ausgabekanal, der nur für Fehlermeldungen gedacht ist, `STDERR`. In normaler Betriebssystemumgebung ist `STDERR` normalerweise ebenso wie `STDOUT` die Bildschirmausgabe. Bei der CGI-Schnittstelle eines Web-Servers geht die Standardfehlerausgabe `STDERR` dagegen meistens in eine Log-Datei des Servers, der solche Fehlermeldungen darin sammelt.

Die drei Kanäle stellen für Perl so genannte Handles dar. Neben diesen Standardkanälen zur Ein- und Ausgabe können Sie als Programmierer eigene Kanäle zur Ein- und Ausgabe öffnen. Dabei vergeben Sie auch eigene Namen für die Handles. Das ist zum Beispiel erforderlich, wenn Sie Daten statt von der Tastatureingabe aus einer Datei lesen wollen oder statt auf den Bildschirm in eine Datei schreiben wollen. Um eine Datei lesen oder schreiben zu können, erzeugen Sie also einfach ein Datei-Handle. Dies passiert beim Öffnen einer Datei - hierzu dient vor allem die Funktion open. Nachdem Sie eine Datei geöffnet und dabei ein Datei-Handle vergeben haben, haben Sie über das Datei-Handle Zugriff auf die Datei.

Perl stellt diverse Funktionen zur Verfügung, um auf Dateien lesend und schreibend zugreifen zu können. Zu einem Datei-Handle gehört ferner ein Dateizeiger. Der Dateizeiger speichert beim Lesen und Schreiben die aktuelle Byteposition innerhalb der Datei. Sie können die Position des Dateizeigers ermitteln und den Dateizeiger zum Beispiel bei Dateien mit bestimmten Dateiformaten an eine andere Position setzen. Auf diese Weise können Sie Schreib- und Lesevorgänge genau steuern.

Für Verzeichnisse - Ordner eines Dateisystems - gibt es eigene Funktionen. Ein Verzeichnis können Sie ebenfalls öffnen. Dann können Sie Einträge des Verzeichnisses lesen, zum Beispiel, um zu ermitteln, ob in dem Verzeichnis Dateien eines bestimmten Typs vorkommen. Verzeichnisfunktionen erkennen Sie an dem `dir` im Namen. So sind etwa `open` oder `seek` Dateifunktionen, während `opendir` und `seekdir` Verzeichnisfunktionen sind.

Neben den normalen Funktionen zum Lesen und Schreiben von Dateien gibt es auch systemnahe Varianten der entsprechenden Funktionen. Benutzen Sie solche Funktionen jedoch nur, wenn Sie einen besonderen Grund dazu haben! Diese Art von Funktionen erkennen Sie am `sys` im Namen. Während beispielsweise `read` eine normale Lesefunktion ist, ist `sysread` die entsprechende systemnahe Variante dieser Funktion.

### Beachten Sie:

Perl-Scripts, die Sie als CGI-Scripts einsetzen, können mit Hilfe dieser Funktionen Dateien auf dem Server-Rechner lesen und schreiben. Auf das Dateisystem eines entfernten Client-Rechners, dessen dort laufender Web-Browser vom Web-Server Daten angefordert hat, haben Sie mit diesen Funktionen keinen Zugriff!

## binmode - Datei binär behandeln

Wichtig, um Binärdateien (z.B. Grafikdateien) korrekt einzulesen oder zurückzuschreiben, wenn das Betriebssystem, unter dem das Perl-Script läuft, zwischen Text- und Binärdateien unterscheidet. Unix macht diese Unterscheidung nicht, die Funktion `binmode` ist deshalb für Perl-Scripts unter Unix bedeutungslos. MS-DOS und MS-Windows dagegen unterscheiden Text- und Binärmodus.
Bei nicht binären Dateien, also bei Klartextdateien, werden die zwei aufeinander folgenden Steuerzeichen CR (Carriage Return) und LF (Line Feed) beim Lesen der Datei unter Betriebssystemen wie DOS/Windows automatisch zu einem LF zusammengefasst. Beim Schreiben einer Textdatei wird jedes LF automatisch wieder in zwei Zeichen CR und LF umgewandelt.
Durch Aufruf der Funktion `binmode` schalten Sie diesen Automatismus aus. So verhindern Sie, dass der Automatismus an Stellen greift, an denen er nicht greifen soll, etwa, wenn Sie numerisch gespeicherte Daten einlesen, die zufällig zwei Bytes in Folge enthalten können, deren Werte den Zeichenwerten für CR und LF entsprechen.

Erwartet als Parameter:
1. das Handle eines Ein-/Ausgabekanals.

### Beispiel eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI::Carp qw(fatalsToBrowser);

    my $AnzahlBytes = -s "/usr/web/src/ship.gif";
    my $Speicher;
    open(GRAFIK, "</usr/web/src/ship.gif");
    binmode(GRAFIK);
    my $geleseneBytes = read(GRAFIK, $Speicher, $AnzahlBytes);
    close(GRAFIK);

    print "Content-type: text/html\n\n";
    print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
    print "<html><head><title>Testausgabe</title></head><body>\n";
    print "<h1>der Inhalt der Grafikdatei als Zeichensalat:</h1>\n";
    print "<p><tt>$Speicher</tt></p>";
    print "</body></html>\n";

### Erläuterung:

Das Beispiel liest eine GIF-Grafikdatei binär ein. Dazu wird die Datei mit open geöffnet. Anschließend wird die Funktkion `binmode` mit dem Datei-Handle der geöffneten Datei (`GRAFIK`) aufgerufen. Danach wird die Datei mit der Funktion read eingelesen.
Zu Testzwecken wird HTML-Code an den aufrufenden Browser gesendet, der den eingelesenen Inhalt der Grafik als Zeichensalat darstellt. Der eingelesene Inhalt befindet sich nach dem Einlesen im Skalar `$Speicher`.

### Beachten Sie:

Weitere Einzelheiten zum Einlesen binärer Dateien werden bei der Funktion read beschrieben.

Der verwendete Ausdruck `-s` zum Feststellen der Dateigröße, gespeichert in `$AnzahlBytes`, gehört zu einer Reihe ähnlicher Ausdrücke, die das Ermitteln von Eigenschaften einer Datei erlauben. Weitere Einzelheiten dazu im Abschnitt über Dateitestoperatoren.

## close - Datei schließen

Schließt eine Datei, die zuvor mit open geöffnet wurde.

Erwartet als Parameter:
1. das Handle eines geöffneten Ein-/Ausgabekanals, der geschlossen werden soll.

### Beispiel mit Erläuterung:

Ein vollständiges Beispiel mit Erläuterung der beiden zusammenhängenden Funktionen `open` und `close` wird bei der Funktion open behandelt!

### Beachten Sie:

Wenn Sie eine zuvor geöffnete Datei nicht explizit mit `close` schließen, wird die Datei von Perl beim Beenden des Scripts automatisch geschlossen.

## closedir - Verzeichnis schließen

Schließt ein Verzeichnishandle, das zuvor mit opendir geöffnet wurde.

Erwartet als Parameter:
1. das Verzeichnishandle.

### Beispiel mit Erläuterung:

Ein vollständiges Beispiel mit Erläuterung der drei zusammenhängenden Funktionen `opendir`, `readdir` und `closedir` wird bei der Funktion opendir behandelt!

## eof - auf Dateiende prüfen

Fragt eine geöffnete Datei daraufhin ab, ob der Dateizeiger das Dateiende erreicht hat.

Erwartet als Parameter:
1. das Handle des Ein-/Ausgabekanals.

Gibt `true` zurück, wenn das Dateiende ereicht ist, und `false`, wenn es nicht erreicht ist.

### Beispiel eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI::Carp qw(fatalsToBrowser);

    my $max = 100000;
    my $i = 0;
    my $Status = 0;

    print "Content-type: text/html\n\n";
    print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
    print "<html><head><title>Testausgabe</title>\n";
    print "</head><body>\n";
    open(DATEI, "</usr/chatlog/lastnight.txt");
    while(1) {
     if(eof(DATEI)) {
       $Status = 1;
       last;
     }
     if($i > $max) {
       $Status = 2;
       last;
     }
     getc(DATEI);
     $i++;
    }
    close(DATEI);
    if($Status == 1) {
     print "<p>Datei war kleiner als $max Bytes, daher ganz gelesen</p>\n";
    }
    if($Status == 2) {
     print "<p>Datei war zu groß, daher nur $max Bytes gelesen</p>\n";
    }
    print "</body></html>\n";

### Erläuterung:

Das Beispiel erzeugt HTML-Code für den aufrufenden Web-Browser. Dabei wird mit der Funktion open eine Textdatei `/usr/chatlog/lastnight.txt` geöffnet. Die geöffnete Datei wird in einer while-Schleife mit der Funktion getc Zeichen für Zeichen eingelesen. Da die Schleifenbedingung `(1)` immer wahr ist, werden innerhalb der Schleife Abbruchbedingungen formuliert. Wenn das Dateiende erreicht ist - `if(eof(DATEI))` - wird der Skalar `$Status` auf 1 gesetzt und die Schleife durch `last` beendet.
Die Schleife wird aber auch dann beendet, wenn mehr Zeichen eingelesen wurden, als in `$max` definiert sind. In diesem Fall wird `$Status` auf 2 gesetzt.
Durch Abfragen des Wertes von `$Status` kann nach Beenden der Schleife festgestellt werden, was die Schleife zum Abbruch gebracht hat. Abhängig davon wird ein entsprechender Satz ausgegeben.

### Beachten Sie:

`if(eof(DATEI))` ("wenn Dateiende erreicht") oder `while(! eof(DATEI))` ("solange Dateiende nicht erreicht") sind typische Formulierungen beim Einsatz der Funktion `eof`. Sinnvoll sind solche Abfragen und Schleifenbedingungen vor allem, wenn Sie Dateien zeichenweise (mit der Funktion `getc`) oder blockweise (mit der Funktion read) einlesen.

## fileno - Nummer einer geöffneten Datei

Jeder geöffnete Ein-Ausgabekanal hat intern eine Nummer, auch die nicht selbst geöffneten Ausgabekanäle `STDIN`, `STDOUT` und `STDERR`. Mit dieser Funktion können Sie die interne Nummer eines Ein-Ausgabekanals ermitteln.

Erwartet als Parameter:
1. das Handle eines Ein-/Ausgabekanals.

Gibt die interne Nummer des Ein-Ausgabekanals zurück.

### Beispiel eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI::Carp qw(fatalsToBrowser);

    print "Content-type: text/html\n\n";
    print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
    print "<html><head><title>Testausgabe</title>\n";
    print "</head><body>\n";
    open(DATEI, "</usr/texte/wichtig.txt");
    my $Datei = fileno(DATEI);
    close(DATEI);
    my $Eingabe = fileno(STDIN);
    my $Ausgabe = fileno(STDOUT);
    my $Fehler = fileno(STDERR);
    print "Eingabe= $Eingabe, Ausgabe = $Ausgabe, Fehler = $Fehler, Datei = $Datei\n";
    print "</body></html>\n";

### Erläuterung:

Das Beispiel erzeugt HTML-Code für den aufrufenden Web-Browser. Dabei wird mit der Funktion open eine Textdatei `/usr/texte/wichtig.txt` geöffnet. Mit `fileno(DATEI)` wird die interne Nummer des Handles dieser Datei ermittelt und in einem Skalar `$Datei` gespeichert. Ebenso werden die internen Nummern der drei Standardkanäle ermittelt und in entsprechenden Skalaren gespeichert. Schließlich gibt das Script die ermittelten Nummern aus.

## flock - geöffnete Datei vor Zugriffen schützen

Regelt, wie andere Prozesse auf eine Datei zugreifen können, während das aktuelle Script die Datei geöffnet hat. Bei CGI-Scripts kann dies sehr wichtig sein. Denn während ein vom Browser eines Anwenders aufgerufenes Script seine Arbeit verrichtet, kann ja bereits ein weiterer Browser eines anderen Anwenders das gleiche Script aufrufen. Die beiden Prozesse arbeiten dann im Arbeitsspeicher des Server-Rechners zwar unabhängig voneinander, führen aber nun mal den gleichen Code aus und greifen auf die gleichen Dateien zu. Damit nicht ein anderer Prozess Daten löscht, die der aktuelle Prozess gerade geschrieben hat, ist es dem Prozess zum Beispiel möglich, die Datei vor Zugriffen zu schützen.

Wichtig: Bei Betriebssystemen, die intern kein `flock` implementiert haben, führt die Anwendung dieser Funktion zu einem Fehler, so etwa auch bei Windows 95/98!

Erwartet als Parameter:
1. das Handle der geöffneten Datei.
2. die Nummer einer Sperroption oder eine Konstante - erlaubt sind die Nummern `1`, `2`, `8` und `4` oder die Konstanten `LOCK_SH`, `LOCK_EX`, `LOCK_UN` und `LOCK_NB`:
Nummer `1` oder Konstante `LOCK_SH` bedeutet shared (Datei mit anderen Prozessen teilen, zum Beispiel, wenn ein Prozess, der lesend auf eine Datei zugreift, andere Prozesse nicht stören soll, die gleichzeitig diese Datei lesen),
Nummer `2` oder Konstante `LOCK_EX` bedeutet exclusive (keinem anderen Prozess irgendeinen Zugriff auf die Datei erlauben),
Nummer `8` oder Konstante `LOCK_UN` bedeutet unlock (Zugriffsschutz ausdrücklich wieder aufheben).
Nummer `4` oder Konstante `LOCK_NB` bedeutet non-blocking (nur in Verbindung mit `1` oder `2` bzw. `LOCK_SH` oder `LOCK_EX` erlaubt und beendet den Zugriffsversuch auf die Datei sofort statt zu warten, bis ein Zugriff möglich ist).
Die Konstanten können Sie nur verwenden, wenn Sie das Modul `Fcntl` einbinden (siehe Beispiel weiter unten).

Gibt `true` zurück, wenn der Vorgang erfolgreich war, und `false`, wenn er nicht erfolgreich war.

### Beispiel eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI::Carp qw(fatalsToBrowser);
    use Fcntl ':flock';
    $| = 1;

    open(DATENDATEI, "</db/daten.csv");
    flock(DATENDATEI, LOCK_EX);

    # angenommen, hier passiert etwas Zeitaufwändiges,
    # und derweil versucht ein anderer Prozess auf die gleiche Datei zuzugreifen
    # dann greift die Sperre

    flock(DATENDATEI, LOCK_UN);
    close(DATENDATEI);

### Erläuterung:

Wenn Sie anstelle der Nummern lieber die Konstanten verwenden möchten, müssen Sie zuerst einen Befehl zum Einbinden des Sperrmoduls notieren, etwa in der obigen Form: `use Fcntl ':flock';`

Nachdem Sie eine Datei erfolgreich geöffnet und ein entsprechendes Datei-Handle für den Zugriff auf die Datei haben, können Sie die Sperroptionen für die Datei festlegen. Im Beispiel geschieht das nach dem Aufruf der open-Funktion mit Hilfe der Anweisung `flock(DATENDATEI, LOCK_EX);`

Dabei ist `DATENDATEI` das Datei-Handle, und `LOCK_EX` die Angabe zur gewünschten Sperroption. Im Beispiel wird die Datei exklusiv gesperrt. Solange die Sperre innerhalb des Scripts nicht aufgehoben oder die Datei geschlossen wird, kann kein anderer Prozess, der `flock` beachtet, gleichzeitig in die Datei schreiben.

### Beachten Sie:

Die beiden Befehle
`flock(DATENDATEI, LOCK_UN);
close(DATENDATEI);`
dienen im obigen Beispiel nur zum besseren Verständnis. Das explizite Beenden der Sperre ist eigentlich überflüssig, wenn es erst beim Schließen der Datei mit der close-Funktion erfolgen soll. Denn `close` hebt zugleich jede Angabe zur Dateisperre auf.

Die Anweisung `$| = 1;` im obigen Beispiel dient zum Ausschalten der gepufferten Ausgabe (vgl. dazu vordefinierte Variablen in Perl). Dies ist beim Sperren von Dateien zu empfehlen. Denn andernfalls kann es passieren, dass durch gepufferte und verzögerte Ausgabe das Schreiben von Daten erst dann stattfindet, wenn die Sperre bereits aufgehoben ist. Dies würde den ganzen Zweck der Sperre überflüssig machen.

Wenn Sie mit der Sperroption `4` bzw. `LOCK_NB` arbeiten möchten, müssen Sie diese Option durch eine bitweise Oder-Verknüpfung mit einer Option zum Sperren verknüpfen. Beispiele:
`flock(DATENDATEI, LOCK_EX | LOCK_NB);
flock(DATENDATEI, LOCK_SH | LOCK_NB);`

Wichtig: `flock` erzwingt keine Sperre, sondern hat nur empfehlenden Charakter. Der Zugriffsschutz ist nur dann wirksam, wenn alle Prozesse, die auf die Datei zugreifen, flock beachten.

## format - Daten vor dem Ausgeben formatieren

Dies ist eine mächtige Funktion, um Daten vor der Ausgabe an einem zeichenorientierten Ausgabegerät wie Textbildschirm oder Zeilendrucker ansprechend zu formatieren. Im Zusammenhang mit CGI-Scripts findet diese Funktion kaum Verwendung, da die wenigsten Web-Browser zeichenorientiert arbeiten.

### Beispiel 1:

    #!/usr/bin/perl -w

    use strict;

    my $Zuname = "Hummel";
    my $Vorname = "Hilde";
    my $Wohnort = "Hammelbach";

    format STDOUT =
    @<<<<<<<<<<<<<  @<<<<<<<<<<<<<  aus @<<<<<<<<<<<<<
    $Vorname, $Zuname, $Wohnort
    .
    write;

### Erläuterung:

In Beispiel 1 wird folgendes ausgegeben:

    Hilde           Hummel          aus Hammelbach

Die Formatierung der Ausgabe geschieht durch das `format`-Konstrukt. Die eigentliche Ausgabe geschieht durch den anschließenden Befehl `write`.

Bei dem Konstrukt zur Formatierung geben Sie hinter `format` einen Namen für das Format an, normalerweise den Namen des gewünschten Datei-Handles. Der Name ist jedoch in Wirklichkeit kein Datei-Handle, er sieht nur so aus. Das Default-Format für ein Datei-Handle hat lediglich den gleichen Namen wie das Datei-Handle. Im obigen Beispiel wird der Formatname `STDOUT`angeben, weil auf die Standardausgabe STDOUT geschrieben werden soll. Hinter dem Formatnamen folgt ein Gleichheitszeichen.
Die Zeilen, die danach folgen, bestehen immer aus Zeilenpaaren. Zuerst werden eine oder mehrere Formatierzeile(n) notiert, und anschließend eine Argumentzeile. In der Formatierzeile definieren Sie mit Hilfe spezieller Zeichensymbole das Ausgabeformat für bestimmte Felder, und in der Argumentzeile nennen Sie die Variablen, die in den entsprechenden Feldern darüber ausgegeben werden.
Mit einem Punkt (.) in einer eigenen Zeile wird das Format-Konstrukt beendet.

Für die Formatierzeile gibt es folgende Regeln:

Anweisung | Bedeutung
--- | ---
`@<<<<<<<` | Feld linksbündig ausrichten. Die Anzahl der `<`-Zeichen bestimmt die Feldbreite in Zeichen. Längere Inhalte werden bei der Ausgabe rechts abgeschnitten.
`@>>>>>>>` | Feld rechtsbündig ausrichten. Die Anzahl der `>`-Zeichen bestimmt die Feldbreite in Zeichen. Längere Inhalte werden bei der Ausgabe rechts abgeschnitten.
`@||||||` | Feld zentriert ausrichten. Die Anzahl der `|`-Zeichen bestimmt die Feldbreite in Zeichen. Längere Inhalte werden bei der Ausgabe rechts abgeschnitten.
`@#.##` | Feld als Zahl mit Dezimalzeichen formatieren. Als Dezimalzeichen ist nur der Punkt erlaubt. Die Anzahl der `#`-Zeichen vor dem Punkt bestimmt die Vorkomma-Feldbreite, kleinere Zahlen werden dabei rechts zum Dezimalzeichen hin ausgerichtet. Die Anzahl der `#`-Zeichen hinter dem Punkt bestimmt die Nachkomma-Feldbreite. Bei weniger Nachkommaziffern als angegebenen Zeichen werden Nullen angehängt.

Zusätzlich zu diesen Formatiermöglichkeiten gibt es einige vordefinierte Variablen, die Sie für die Ausgabe benutzen können.

### Beispiel 2:

    #!/usr/bin/perl -w

    use strict;

    format STDOUT =
    Seite @<<    @>>>>>>>
    $%, $~
    .
    write;

### Erläuterung:

In Beispiel 2 wird folgendes ausgegeben:

    Seite 0        STDOUT

Die Formatierung der Ausgabe geschieht durch ein `format`-Konstrukt. Anstelle gewöhnlicher Variablen werden jedoch spezielle, vordefinierte Variablen ausgegeben. Folgende spezielle Variablen sind möglich:

Anweisung | Bedeutung
--- | ---
`$%` | aktuelle Seitennummer
`$=` | Anzahl Zeilen pro Seite
`$-` | Anzahl übrig gebliebener Zeilen auf der aktuellen Seite
`$~` | Name des aktuellen Formats - per Voreinstellung der Name des benutzten Datei-Handles.
`$^` | Name des aktuellen Kopfseitenformats - per Voreinstellung der Name aktuellen Formats plus der Zeichenfolge `_TOP`.
`$:` | Trennzeichen(folge) bei mehrzeiligen Einträgen.
`$^L` | Trennzeichen(folge) für Seitentrenner.

Für längere Ausgaben, zum Beispiel von Dateien, können Sie auch Kopfzeilen benutzen. Das folgende Beispiel zeigt, wie Sie eine Datei ausgeben können:

### Beispiel 3:

    #!/usr/bin/perl -w

    use strict;
    my $Zeile;

    open(DATEI,"</usr/texte/daten.txt");

    format STDOUT_TOP =
    ****************************************************
    Seite @>>
    $%
    ****************************************************
    .

    format STDOUT =
    @<<<<<<<<<<<<<<<
    $Zeile;
    .

    while(<DATEI>) {
      chomp $_;
      $Zeile = $_;
      write;
    }
    close(DATEI);

### Erläuterung:

In Beispiel 3 werden von einer angenommenen Textdatei von jeder Zeile die ersten 15 Zeichen ausgegeben.

Die Formatierung der Ausgabe in Beispiel 3 geschieht durch zwei `format`-Konstrukte. Die beiden Konstrukte erhalten die Namen `STDOUT_TOP` und `STDOUT`. Durch die Zeichenfolge `_TOP` am Ende eines Formatnamens teilen Sie Perl mit, dass es sich um eine Kopfzeilendefinition handelt. Im Beispiel wird die Kopfzeile durch zwei Linien, bestehend aus Sternchen, und dazwischen der aktuellen Seitenzahl formatiert.

Im weiteren Verlauf von Beispiel 3 sehen Sie, wie die Datei in einer while-Schleife zeilenweise in eine Variable namens `$Zeile` eingelesen wird. Diese Variable wird - ebenfalls in der Schleife - jeweils ausgegeben. Für die Formatierung der Ausgabe ist das Format-Konstrukt mit dem Namen `STDOUT` verantwortlich. Dort wird die Variable `$Zeile` in der gewünschten Form ausgegeben.

### Beachten Sie:

Die Variable `$Zeile` muß im obigen Beispiel global deklariert werden. Daher die Anweisung `use vars qw($Zeile);` zu Beginn.

## getc - nächstes Zeichen lesen

Liest ein Zeichen aus einer zuvor geöffneten Datei und positioniert den Dateizeiger um ein Zeichen weiter.

Erwartet als Parameter:
1. das Datei-Handle.

### Beispiel eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI::Carp qw(fatalsToBrowser);

    print "Content-type: text/html\n\n";
    print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
    print "<html><head><title>Testausgabe</title>\n";
    print "</head><body><pre>\n";
    open(DATEI, "</usr/texte/wichtig.txt");
    my $Bytes = 0;
    while(! eof(DATEI)) {
     my $Zeichen = getc(DATEI);
     print "$Zeichen";
     $Bytes++;
    }
    close(DATEI);
    print "</pre><b>$Bytes Zeichen gelesen!</b>\n";
    print "</body></html>\n";

### Erläuterung:

Das Beispiel erzeugt HTML-Code für den aufrufenden Web-Browser. Dabei wird auch mit der Funktion open eine Textdatei `/usr/texte/wichtig.txt` geöffnet. Die geöffnete Datei wird in einer while-Schleife Zeichen für Zeichen eingelesen, bis das Dateiende, das mit der Funktion eof abgefragt wird, erreicht ist. Die eingelesenen Zeichen werden ausgegeben. Außerdem wird der Skalar `$Bytes` bei jedem eingelesenen Zeichen um 1 erhöht. Auf diese Weise wird nebenbei die Anzahl der eingelesenen Zeichen ermittelt. Am Ende wird diese Anzahl auch mit ausgegeben.

## open - Datei öffnen

Öffnet eine Datei zum Lesen und/oder Schreiben oder auch zum Ausführen. Auch Binärdateien werden mit dieser Funktion geöffnet.

Erwartet als Parameter:
1. den Namen des Datei-Handles (frei wählbar), und
2. den Pfadnamen der zu öffnenden Datei, entweder als absolute Pfadangabe, oder als relative Pfadangabe aus Sicht des aktuellen Verzeichnisses (wenn das aktuelle Verzeichnis unbekannt ist, empfiehlt es sich, mit Hilfe der Funktion chdir in ein bestimmtes Verzeichnis zu wechseln). Als Trennzeichen für Verzeichnispfade können Sie den einfachen Schrägstrich verwenden, auch wenn das Script auf einem Windows/DOS-Rechner laufen soll. Perl setzt diese Syntax je nach Installationsumgebung intern um.
URIs können Sie jedoch nicht angeben!

Unmittelbar vor dem (Pfad)namen der zu öffnenden Datei notieren Sie mit Hilfe der Zeichen `<`, `>` und `|` außerdem, wie die Datei geöffnet werden soll. Wenn Sie keine dieser Angaben machen, wird die Datei nur zum Lesen geöffnet. Folgende Angaben sind erlaubt:
`<datei.dat` bedeutet: Datei `datei.dat` nur zum Lesen öffnen. Die Datei muss existieren, ansonsten gibt es einen Fehler.
`>datei.dat` bedeutet: Datei `datei.dat` zum Schreiben von Daten öffnen. Wenn die Datei bereits existiert, wird ihr bisheriger Inhalt überschrieben. Wenn die Datei noch nicht existiert, wird sie automatisch angelegt.
`>>datei.dat` bedeutet: Datei `datei.dat` zum Schreiben von Daten öffnen. Wenn die Datei bereits existiert, wird der neue Inhalt an den alten Inhalt angehängt, d.h. der alte Inhalt wird nicht gelöscht. Wenn die Datei noch nicht existiert, wird sie automatisch angelegt.
`+>datei.dat` bedeutet: Datei `datei.dat` zum Lesen und zum Schreiben von Daten öffnen.
`|datei` bedeutet: Datei `datei` ist eine ausführbare Programmdatei oder ein Shell-Befehl. Das Programm bzw. der Befehl werden ausgeführt. Aus Unix-Sicht wird dabei eine Pipe zu dem Programm bzw. Befehl geöffnet.
`datei|` bedeutet: Datei `datei` ist eine ausführbare Programmdatei oder ein Shell-Befehl. Das Programm bzw. der Befehl werden ausgeführt. Aus Unix-Sicht wird dabei eine Pipe von dem Programm bzw. dem Befehl geöffnet.

Wenn die Datei geöffnet werden kann, gibt die Funktion `open` den Wert `true` zurück, andernfalls den Wert `undef`.

### Beispiel:

    #!/usr/bin/perl -w

    use strict;

    open(DATEI, "</tmp/server.cfg") || die "Datei nicht gefunden";
    my @Zeilen = <DATEI>;
    close(DATEI);

    my @NeueZeilen;
    foreach(@Zeilen) {
      $_ =~ s/#.*//;
      push(@NeueZeilen,$_) if $_ !~ /^\s*\n/;
    }
    open(DATEI, ">/tmp/server.cfg") || die "Datei nicht gefunden";
    print DATEI @NeueZeilen;
    close(DATEI);

### Erläuterung:

Das Beispiel zeigt, wie Sie eine Datei öffnen, einlesen, verarbeiten und schließen, dann wieder öffnen und den neu verarbeiten Datenbestand in die Datei zurückschreiben. Es handelt sich um eine angenommene Konfigurationsdatei, in der viele Zeilen hinter dem eigentlichen Konfigurationsbefehl Kommentare enthalten, die mit `#` beginnen. Im Beispiel wird die Datei so verarbeitet, dass alle diese Kommentarzeilen gelöscht werden.

Zunächst wird die `open`-Funktion aufgerufen. Dabei wird die gewünschte Datei zum Lesen geöffnet. Die Datei wird dann in den Array `@Zeilen` eingelesen (in jedem Eintrag von `@Zeilen` steht anschließend je eine Zeile der Datei). Nach dem Einlesen wird die Datei mit close wieder geschlossen.
Diese drei Befehle zum Öffnen, Einlesen und Schließen sind typisch.

Im obigen Beispiel werden die eingelesenen Zeilen anschließend der Reihe nach in einer foreach-Schleife verarbeitet. Dabei wird in jeder Zeile der Kommentarteil entfernt. Dies geschieht in dem regulären Ausdruck zum Suchen/Ersetzen (`s/#.*//g`). Dann wird die aktuell verarbeitete Zeile mit push dem Array `@NeueZeilen` hinzugefügt - aber nur dann, wenn die Zeile aus etwas anderem besteht als nur aus Leerraumzeichen mit abschließendem Newline-Zeichen. Auch dazu wird wieder ein geeigneter regulärer Ausdruck angewendet.

Schließlich wird die Datei wieder geöffnet, diesmal jedoch zum Schreiben, genauer gesagt: zum Überschreiben des bisherigen Inhalts. Mit Hilfe der print-Funktion wird der Array `@NeueZeilen` in die Datei geschrieben. Anschließend wird die Datei geschlossen.

### Beachten Sie:

Wenn Fehler beim Öffnen von wichtigen Dateien passieren, ist es meistens sinnvoll, das Script sofort zu beenden. Dazu dient die Funktion die, die auch im obigen Beispiel zum Einsatz kommt.

In den meisten Fällen ist es sinnvoll, eine geöffnete Datei sofort wieder zu schließen, sobald Sie sie nicht mehr zum Lesen oder Schreiben brauchen. Dadurch geben Sie Betriebssystem-Ressourcen frei, und andere Programme oder Prozesse können ebenfalls wieder auf die Datei zugreifen, wenn Sie die Datei zuvor gesperrt hatten.

## opendir - Verzeichnis öffnen

Öffnet ein Verzeichnis, zum Beispiel, um es auszulesen. Dabei vergeben Sie ein Verzeichnishandle, über das Sie auf das Verzeichnis zugreifen können.

Erwartet als Parameter:
1. den Namen des Verzeichnishandles (frei wählbar), und
2. den Pfadnamen des zu öffnenden Verzeichnisses, entweder als absolute Pfadangabe, oder als relative Pfadangabe aus Sicht des aktuellen Verzeichnisses (wenn das aktuelle Verzeichnis unbekannt ist, empfiehlt es sich, mit Hilfe der Funktion chdir in ein bestimmtes Verzeichnis zu wechseln).

Gibt `TRUE` zurück, wenn das Verzeichnis geöffnet werden konnte. Wenn ein Fehler aufgetreten ist, wird dieser in der Variablen `$!` gespeichert.

### Beispiel eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI::Carp qw(fatalsToBrowser);

    my $Verzeichnis = "/daten/web";
    opendir(DIR, $Verzeichnis) || die "$Verzeichnis: $!";
    my @Eintraege = readdir(DIR);
    closedir(DIR);

    print "Content-type: text/html\n\n";
    print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
    print "<html><head><title>Testausgabe</title></head><body>\n";
    foreach(@Eintraege) {
     print "$_<br>\n";
    }
    print "</body></html>\n";

### Erläuterung:

Im Beispiel wird in dem Skalar `$Verzeichnis` der Pfad eines Verzeichnisses gespeichert (`"/daten/web"`). Beachten Sie, dass die Verzeichnisse des Pfades durch einfache Schrägstriche getrennt sind, nicht durch Backslashes wie unter DOS/Windows üblich. Verwenden Sie die Syntax mit den einfachen Schrägstrichen auch dann, wenn Perl bei Ihnen unter DOS/Windows läuft. Wenn Sie in einer DOS/Windows-Umgebung ein anderes als das aktuelle Laufwerk ansprechen möchten, setzen Sie einfach den Laufwerksbuchstaben mit Doppelpunkt davor, also beispielsweise `c:/temp`.

Mit der Funktion `opendir` wird das Verzeichnis geöffnet. `DIR` ist ein selbst vergebener Name für das Verzeichnishandle. Ferner bekommt die Funktion den Skalar übergeben, in dem das gewünschte Verzeichnis gespeichert ist. Falls das Verzeichnis nicht geöffnet werden kann, endet das Script durch Aufruf der Funktion die.

Das obige Beispiel nutzt das geöffnete Verzeichnis, um mit Hilfe der Funktion readdir den Verzeichnisinhalt in eine Liste `@Eintraege` einzulesen. Anschließend wird das Verzeichnis durch Aufruf der Funktion closedir geschlossen. Das Beispiel sendet dann HTML-Code an einen aufrufenden Browser. Dabei wird die Liste der Verzeichniseinträge ausgegeben.

### Beachten Sie:

Es werden alle Verzeichniseinträge eingelesen, also Dateinamen, aber auch Namen von Unterverzeichnissen, sowie die auf den meisten Systemen vorhandenen "symbolischen" Verzeichnisnamen mit einem Punkt (`.`) (steht für das aktuelle Verzeichnis) und zwei Punkten (`..`) (steht für das Elternverzeichnis).

## print - Daten ausgeben

Schreibt Daten auf die Standardausgabe oder in einen geöffneten Ausgabekanal, also etwa in eine Datei. Die Daten können eine einzelne Zeichenkette oder eine Liste von Zeichenketten sein. Innerhalb solcher Zeichenketten können auch Variablen vorkommen, also einzelne Skalare, aber auch ganze Listen oder Hashes. Perl erkennt die Variablen und schreibt ihren aktuellen Wert an die entsprechende Stelle.
Diese Funktion wird in CGI-Scripts sehr oft verwendet, um HTML-Code an den Browser zu senden.

Erwartet als Parameter:
1. Datei-Handle = Optionale Angabe zum Ausgabekanal. Wenn Sie diese Angabe weglassen, wird auf die Standardausgabe `STDOUT` geschrieben. Wenn Sie mit open eine Datei geöffnet haben und in diese schreiben wollen, müssen Sie das bei `open` vergebene Datei-Handle angeben.
2. Daten[,Daten] = Ein oder mehrere Elemente (Zeichenketten, Zahlen usw.), die geschrieben werden sollen.

Gibt `true` zurück, wenn Perl die Daten erfolgreich schreiben konnte.

### Beispiel 1 eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI::Carp qw(fatalsToBrowser);

    print "Content-type: text/html\n\n";
    print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
    print "<html><head><title>Testausgabe</title></head><body>\n";
    print "<table border=\"1\">\n","<tr><td><b>Umgebungsvariable</b></td><td><b>Aktueller Wert</b></td></tr>\n";
    my $i = 0;
    my $Eintrag;
    foreach $Eintrag (%ENV) {
      if($i == 0) {
        print "<tr><td>$Eintrag</td>\n";
      }
      else {
        print "<td>$Eintrag</td></tr>\n";
      }
      if($i == 0) {
        $i = 1;
      }
      else {
        $i = 0;
      }
    }
    print "</table>\n","</body></html>\n";

### Erläuterung:

Das Beispiel gibt alle CGI-Umgebungsvariablen des Web-Servers aus, und zwar sauber als HTML-Tabelle formatiert. Dazu werden die Einträge des vordefinierten Hashes `%ENV` in einer foreach-Schleife abgearbeitet und in die HTML-Tabelle geschrieben. Die entsprechenden HTML-Ausgaben werden mit Hilfe von print-Befehlen geschrieben.

Im letzten der `print`-Befehle können Sie sehen, wie man mehrere Zeichenketten, durch Kommata getrennt, hintereinander notieren kann.
In den `print`-Befehlen innerhalb der Schleife können Sie sehen, wie eine Variable (im Beispiel der Skalar `$Eintrag`) innerhalb einer auszugebenden Zeichenkette notiert ist. An der entsprechenden Stelle wird dann der jeweils aktuelle Wert von `$Eintrag` ausgegeben.

Wenn Sie viele `print`-Befehle hintereinander notieren müssen, können Sie auch zu einer lesbareren Lösung greifen:

### Beispiel 2 eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI::Carp qw(fatalsToBrowser);

    print "Content-type: text/html\n\n";
    print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
    print <<"ENDE";
    <html>
    <head>
    <title>Titel</title>
    </head>
    <body bgcolor="#FFFFCC">
    <h1>Ganz normales HTML</h1>
    <p>Perl und HTML sind manchmal wie Adam und Eva</p>
    </body>
    </html>
    ENDE

### Erläuterung:

Sie können größere Textabschnitte, zum Beispiel kompletten HTML-Code, in einem Stück ausgeben. Dazu notieren Sie hinter dem `print`-Befehl zwei `<<` und direkt dahinter (ohne Leerzeichen dazwischen) den Namen eines Endbegrenzers, bis zu dem alles einfach als Text ausgegeben werden soll. Hinter dem Namen des Endbegrenzers folgt in der Zeile des `print`-Befehls das übliche Semikolon. Am Ende des auszugebenden Textes notieren Sie in einer eigenen Zeile den Namen des Endbegrenzers, dort jedoch ohne Semikolon am Ende. Es hat sich eingebürgert, für solche Namen von Labels Großbuchstaben zu verwenden, weil die Label so im Quelltext leichter sichtbar sind.

### Beachten Sie:

Bei CGI-Scripts kann der Inhalt der ausgegebenen Daten auch als HTTP-Befehl interpretiert werden. Die Anweisung:
`print "Content-type: text/html\n\n";`
ist ein typisches Beispiel dafür. Dabei wird ein einfacher HTTP-Header gesendet, der für die Kommunikation zwischen Server und Browser erforderlich ist. Eine andere, für CGI-Scripts interessante Variante ist die folgende Anweisung (Beispiel):
`print "Location: http://www.teamone.de/\n\n";`
Auch dabei wird ein HTTP-Header ausgegeben, der eine Weiterleitung zu dem angegebenen URI bewirkt. Ein CGI-Script, das eine solche `Location`-Anweisung enthält, braucht sonst keinen weiteren HTML-Code an den Browser zu senden.

## printf - Daten formatiert ausgeben

Schreibt Daten auf die Standardausgabe oder in einen geöffneten Ausgabekanal, also etwa in eine Datei. Diese Funktion dient dazu, um einzelne Datenelemente formatiert auszugeben. So lassen sich Dezimalzahlen beispielsweise ohne viel Umrechnung hexadezimal ausgeben, oder die Ausgabe von Gleitkommazahlen mit vielen Nachkommastellen lässt sich auf eine bestimmte Anzahl Nachkommastellen trimmen.
Die printf-Funktion in Perl entspricht im wesentlichen der printf-Funktion in C.

Erwartet als Parameter:
1. Datei-Handle = Optionale Angabe zum Ausgabekanal. Wenn Sie diese Angabe weglassen, wird auf die Standardausgabe STDOUT geschrieben. Wenn Sie mit open eine Datei geöffnet haben und in diese schreiben wollen, müssen Sie das bei `open` vergebene Datei-Handle angeben.
2. Formatstring = eine Zeichenkette, die für bestimmte auszugebende Elemente Formatbezeichner enthalten kann, und zwar entsprechend der speziellen Syntax der printf-Funktion (%-Zeichen-Syntax).
3. Ausgabeliste = ein oder mehrere Elemente, auf die sich die speziellen Formatbezeichner im Formatstring beziehen.

### Beispiel eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI::Carp qw(fatalsToBrowser);

    my $BruttoBetrag = 27.95;
    my $NettoBetrag = $BruttoBetrag / 1.16;

    print "Content-type: text/html\n\n";
    print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
    print "<html><head><title>Testausgabe</title></head><body>\n";
    printf "Das im Bruttobetrag %s enthaltene Netto beträgt ungerundet %.2f", $BruttoBetrag, $NettoBetrag;
    print "</body></html>\n";

### Erläuterung:

Das Beispiel gibt mit Hilfe der `printf`-Funktion die beiden Variablen `$BruttoBetrag` und `$NettoBetrag` aus. Der Wert von `$NettoBetrag` wird rechnerisch gewonnen und stellt eine Bruchzahl mit vielen Nachkommastellen dar. In der Ausgabe mit `printf` wird diese Zahl jedoch auf zwei Nachkommastellen reduziert ausgegeben.

Dazu notieren Sie in der auszugebenden Zeichenkette an der gewünschten Stelle einen Formatbezeichner. Solche Formatbezeichner beginnen mit einem Prozentzeichen `%`. Dahinter folgen die Angaben zur Formatierung. Die folgende Tabelle listet die möglichen Formatbezeichner und deren Formatiermöglichkeiten auf.

Syntax | Bedeutung | Beispiel | Bewirkte Ausgabe
--- | --- | --- | ---
`%c` | gibt das ASCII-Zeichen eines numerischen Zeichenwertes aus. Die Zahl kann z.B. dezimal oder hexadezimal angegeben werden. | `printf "%c wie Paula", 0x50;` | P wie Paula
`%d` | gibt den Ganzzahlanteil einer Zahl in Dezimaldarstellung aus. Optional kann hinter dem `%`-Zeichen und vor dem `d` noch eine gewünschte Anzeigebreite der Zahl angegeben werden, z.B. `%5d`. In Verbindung mit HTML-Ausgaben ist dies jedoch nur innerhalb von Tags wie `<pre>`...`</pre>` realisierbar. | `$PI = 3.141592653589793; printf "Der Ganzzahlanteil von PI ist %d", $PI;` | Der Ganzzahlanteil von PI ist 3
`%e` | gibt eine Zahl in Exponentialschreibweise aus | `$PI = 3.141592653589793; printf "PI exponential: %e", $PI;` | PI exponential: 3.141593e+000
`%E` | wie %e, nur mit E als Exponentialzeichen statt e. | `$PI = 3.141592653589793; printf "PI exponential: %E", $PI;` | PI exponential: 3.141593E+000
`%f` | gibt eine Zahl mit Dezimalpunktdarstellung aus. Die Zahl nach dem Punkt ist die gewünschte Anzahl Nachkommastellen für die Ausgabe. Automatisch gerundet wird dabei nicht! | `$Preis = 99; printf "Der Preis beträgt %.2f", $Preis;` | Der Preis beträgt 99.00
`%g` | gibt eine Zahl automatisch in Exponentialschreibweise (wie bei %e) oder in Dezimalpunktdarstellung (wie bei %f) aus, abhängig von der Beschaffenheit der Zahl. | `$Zahl1 = 100, $Zahl2 = 10000000000000000; printf "Die Zahlen: %g und %g", $Zahl1, $Zahl2;` | Die Zahlen: 100 und 1e+016
`%G` | wie %g, nur mit E als Exponentialzeichen statt e. | `$Zahl = 10000000000000000; printf "Die Zahl lautet %G", $Zahl;` | Die Zahl lautet 1E+016
`%o` | gibt eine Zahl in oktaler Schreibweise aus, ansonsten wie `%u`. Das Oktalsystem kennt nur Ziffern von 0 bis 7. | `$Zahl = 100; printf "die Zahl lautet oktal %o", $Zahl;` | Die Zahlen lautet oktal 144
`%u` | gibt eine Zahl als unsigned integer, also als positive Ganzzahl aus. Wenn die Zahl negativ ist, gibt Perl sie als die Differenz von der höchsten möglichen Integerzahl (4294967296) und der Zahl aus. | `$Zahl1 = 100, $Zahl2 = -100; printf "Die Zahlen: %u und %u", $Zahl1, $Zahl2;` | Die Zahlen: 100 und 4294967196
`%s` | gibt eine Zeichenkette (String) aus. | `printf "PATH ist %s", $ENV{'PATH'};` | PATH ist D:\PERL\BIN;C:\WINDOWS (Beispielausgabe)
`%x` | gibt eine Zahl in hexadezimaler Schreibweise aus, ansonsten wie `%u`. Das Hexadezimalsystem kennt als Ziffern 0 bis 9 und a bis f. | `$Zahl = 200; printf "die Zahl lautet oktal %x", $Zahl;` | Die Zahlen lautet hexadezimal c8
`%X` | wie %x, nur mit A bis F als Ziffern statt a bis f. | `$Zahl = 200; printf "die Zahl lautet oktal %X", $Zahl;` | Die Zahlen lautet hexadezimal C8
`%%` | notieren Sie, um das Formatbezeichnerzeichen, also das Prozentzeichen, selber auszugeben. | `$Level = 100; printf "wir haben %d%% erreicht", $Level;` | wir haben 100% erreicht

Zusätzlich zu diesen Formatbezeichnern stehen so genannte Flags zur Verfügung, mit deren Hilfe sich die Ausgabe noch feiner justieren lässt. Flags müssen unmittelbar hinter dem Prozentzeichen für Formatbezeichner notiert werden. Die folgende Tabelle listet mögliche Flags auf:

Syntax | Bedeutung | Beispiel | Bewirkte Ausgabe
--- | --- | --- | ---
`[blank]` | Leerzeichen vor positiven Zahlen erzwingen. Sinnvoll, wenn diese in Kolonne mit anderen Zahlen stehen, die auch negativ sein können. | `$Zahl1 = 100, $Zahl2 = -100; printf "% d%\n% d", $Zahl1, $Zahl2;` | 100 -100
`-` | Zahlen mit erzwungener Anzeigebreite linksbündig ausrichten (Voreinstellung ist rechtsbündig). | `printf "%-10d Zugriffe", 1234;` | 1234 Zugriffe
`0` | Zahl mit erzwungener Anzeigebreite mit Nullenauffüllen falls die Zahl kleiner ist. | `printf "%010d Zugriffe", 1234;` | 0000001234 Zugriffe
`#` | Hexadezimal- oder Oktalzahl mit entsprechendem Bezeichner für die übliche Schreibweise versehen. | `printf "100 Hex = %#x, 100 Okt = %#o", 100, 100;` | 100 Hex = 0x64, 100 Okt = 0144

## read - bestimmte Anzahl Zeichen lesen

Liest eine anzugebende Anzahl Zeichen aus einer Datei ab der aktuellen Position des Dateizeigers in einen Skalar ein.

Erwartet als Parameter:
1. das Datei-Handle.
2. einen Skalar, in dem die eingelesenen Zeichen gespeichert werden.
3. die Anzahl der zu lesenden Zeichen.
4. (optional) Offset - wenn die Zeichen in dem Zeichenkettenskalar (2.), in den eingelesen werden, nicht ab dem ersten Zeichen beginnen sollen, sondern ab einem Zeichen n, das als Offset angegeben wird (die Zählung beginnt bei 0).

Gibt die Anzahl eingelesener Zeichen zurück. Wenn das Dateiende erreicht wurde, wird `0` zurückgegeben. Wenn ein Fehler auftritt, wird `undef` zurückgegeben.

### Beispiel - Teil 1 (Datei error.log):

    [Sat Feb 03 17:24:44 2001] [error] [client 127.0.0.1] File does not exist: /usr/web/src/formate.css

### Beispiel - Teil 2 (als vollständiges CGI-Script in Perl):

    #!/usr/bin/perl -w

    use strict;
    use CGI::Carp qw(fatalsToBrowser);

    print "Content-type: text/html\n\n";
    print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
    print "<html><head><title>Testausgabe</title>\n";
    print "</head><body>\n";
    my $Ausgabe;
    open(ERRORDATEI, "</usr/logs/error.log") || die "Log-Datei nicht gefunden!";
    my $geleseneZeichen = read(ERRORDATEI, $Ausgabe, 26);
    close(ERRORDATEI);
    print "gelesene Zeichen: $geleseneZeichen; gelesener Inhalt: $Ausgabe\n";
    print "</body></html>\n";

### Erläuterung:

Das Beispiel zeigt im ersten Teil den Inhalt einer Datei namens error.log. Die Datei enthält eine Zeile, in der ein aufgetretener Fehler protokolliert ist. Im zweiten Teil des Beispiels liest ein CGI-Script diese Datei aus, aber nicht komplett, sondern nur 26 Zeichen. Da der Dateizeiger nach dem Öffnen der Datei mit open auf 0 steht, liest der im Beispiel notierte `read`-Befehl die ersten 26 Zeichen aus der Datei. Zur Kontrolle gibt das Script im Beispiel die Anzahl der eingelesenen Zeichen aus, die es durch den Rückgabewert von `read` in dem Skalar `$geleseneZeichen` ermittelt. Ferner gibt das Script die eingelesene Zeichenkette aus. Im Beispiel ist das genau der Teil, der den Zeitstempel in der Datei error.log markiert, also `[Sat Feb 03 17:24:44 2001]`. Dies sind die ersten 26 Zeichen.

### Beachten Sie:

Um den Dateizeiger vor dem Lesen mit `read` an eine andere Stelle zu positionieren, können Sie die Funktion seek verwenden.

## readdir - Verzeichniseinträge ermitteln

Liest Einträge in einem Verzeichnis, das zuvor mit der Funktion opendir geöffnet wurde.

Erwartet als Parameter:
1. das Verzeichnishandle, das bei `opendir` vergeben wurde.

Gibt den jeweils nächsten Verzeichniseintrag zurück, wenn der Rückgabewert in einem Skalar gespeichert wird, zum Beispiel:
`$Eintrag = readdir(DIR);`
Gibt alle Einträge des Verzeichnisses zurück, wenn der Rückgabewert in einer Liste gespeichert wird, zum Beispiel:
`@Eintraege = readdir(DIR);`
Verzeichniseinträge sind sichtbare Dateien, Verzeichnisse sowie die Platzhalter für das aktuelle Verzeichnis (`.`) und für das nächsthöhere Verzeichnis (`..`).

### Beispiel eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI::Carp qw(fatalsToBrowser);

    my $Verzeichnis = "/usr/web/ars_vivendi";
    my $URIVerzeichnis = "/ars_vivendi";
    opendir(DIR, $Verzeichnis) || die "$Verzeichnis: $!";
    my @Dateien = readdir(DIR);
    closedir(DIR);

    print "Content-type: text/html\n\n";
    print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
    print "<html><head><title>Testausgabe</title></head><body>\n";
    foreach(@Dateien) {
     if($_ =~ /.+\.htm*/) {
       print "<a href=\"$URIVerzeichnis/$_\">$URIVerzeichnis/$_</a><br>\n";
       }
    }
    print "</body></html>\n";

### Erläuterung:

Im Beispiel wird in dem Skalar `$Verzeichnis` der Pfad eines Verzeichnisses gespeichert (`"/usr/web/ars_vivendi"`). In einem zweiten Skalar `$URIVerzeichnis` wird ein zweiter Pfad (`"/ars_vivendi"`) gespeichert. Der Grund ist, dass im Beispiel `"/usr/web"` als Wurzelverzeichnis (document root) des installierten Web-Servers ist. Dann ist `"/ars_vivendi"` ein Verzeichnis unterhalb der document root.

Mit der Funktion `opendir` wird das Verzeichnis geöffnet. Mit Hilfe von `readdir` wird der Verzeichnisinhalt in eine Liste `@Dateien` eingelesen. Anschließend wird das Verzeichnis durch Aufruf der Funktion closedir geschlossen.

Das Beispiel sendet dann HTML-Code an einen aufrufenden Browser. Dabei wird die Liste der Verzeichniseinträge analysiert. Einträge, in denen das Suchmuster `.+\.htm*` vorkommt, werden zeilenweise ausgegeben, und zwar umrahmt von HTML-Auszeichnungen, die den jeweiligen Eintrag als Verweis anklickbar machen. Zur korrekten Adressierung der anklickbaren HTML-Dateinamen wird der Skalar `$URIVerzeichnis` verwendet.

## rewinddir - auf ersten Verzeichniseintrag positionieren

Positioniert den Lesezeiger in einem Verzeichnis, das zuvor mit der Funktion opendir geöffnet wurde, wieder auf den ersten Eintrag. Dies kann sinnvoll sein, wenn Sie das Verzeichnis mit readdir bereits eingelesen haben, das Verzeichnishandle aber zu einem erneuten Einlesen des Verzeichnisinhalts verwenden möchten.

Erwartet als Parameter:
1. das Verzeichnishandle, das bei `opendir` vergeben wurde.

### Beispiel eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI::Carp qw(fatalsToBrowser);

    my $Verzeichnis = "/usr/work";
    print "Content-type: text/html\n\n";
    print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
    print "<html><head><title>Testausgabe</title></head><body>\n";
    opendir(DIR, $Verzeichnis) || die "$Verzeichnis: $!";
    my @Eintraege = readdir(DIR);
    my $Eintrag;
    foreach $Eintrag (@Eintraege) {
     if($Eintrag =~ /.+\.bak/) {
        unlink($Verzeichnis."/".$Eintrag);
       }
    }
    rewinddir(DIR);
    @Eintraege = "";
    @Eintraege = readdir(DIR);
    foreach $Eintrag (@Eintraege) {
     print "$Eintrag<br>\n";
    }
    print "</body></html>\n";
    closedir(DIR);

### Erläuterung:

Das Beispiel liest zunächst alle Einträge des Verzeichnisses `$Verzeichnis` in die Liste `@Eintraege` ein. Diese Liste wird anschließend nach Dateien des Typs *.bak (typische Endung für Sicherungs-Dateien) durchsucht. Dateien mit dieser Endung werden im Beispiel gelöscht (mit unlink). Nachdem diese Aktion beendet ist, wird der Verzeichniszeiger mit `rewinddir(DIR)` zurückgesetzt, denn das Verzeichnis soll nun mit dem gleichem, immer noch geöffneten Verzeichnishandle `DIR` nochmals eingelesen werden. Beim zweiten Einlesen werden alle vorhandenen Einträge ausgegeben. Dateien des Typs *.bak sollten eigentlich nicht mehr dabei sein. Oft geschieht das Neueinlesen jedoch noch, bevor die Dateien vom Betriebssystem gelöscht sind, und es werden deshalb doch noch die alten Einträge ausgegeben.

## seek - Dateizeiger positionieren

Positioniert den Dateizeiger eines Dateihandles, das zuvor mit open erzeugt wurde, an eine beliebige Stelle innerhalb der Datei.

Erwartet als Parameter:
1. das Handle der geöffneten Datei.
2. Byteposition innerhalb der Datei, abhängig von der im dritten Parameter angegebenen Bezugsposition
3. Bezugsposition für die Angabe im zweiten Parameter. Diese kann die Werte 0, 1 oder 2 haben:
0 bedeutet absolut vom Dateianfang (Position 0) aus gerechnet,
1 bedeutet relativ vom der aktuellen Position des Dateizeigers aus gerechnet,
2 bedeutet absolut vom Dateiende gerechnet (im Normalfall sollte die Angabe beim zweiten Parameter in diesem Fall eine negative Zahl sein).

### Beispiel - Teil 1 (Datei isbn.txt):

    ISBN 3-7723-7514-6

### Beispiel - Teil 2 (vollständiges CGI-Script in Perl):

    #!/usr/bin/perl -w

    use strict;
    use CGI::Carp qw(fatalsToBrowser);

    my $Datei = "isbn.txt";
    my $ISBNummer;
    open(DATEI, "<$Datei");
    seek(DATEI, 5, 0);
    read(DATEI, $ISBNummer, 13);
    close(DATEI);
    print "Content-type: text/html\n\n";
    print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
    print "<html><head><title>Testausgabe</title>\n";
    print "ISBN-Nummer: $ISBNummer";
    print "</body></html>\n";

### Erläuterung:

Das Beispiel zeigt im ersten Teil den Inhalt einer Datei namens isbn.txt. Die Datei enthält eine Zeile, in der eine ISBN-Nummer notiert ist, wobei die eigentliche ISBN-Nummer jedoch erst an Position 5 beginnt. Im zweiten Teil des Beispiels liest ein CGI-Script diese Datei aus, aber nicht komplett, sondern nur ab Position 5, und von dort an 13 Zeichen. Da der Dateizeiger nach dem Öffnen der Datei mit open auf 0 steht, wird er mit `seek(DATEI, 5, 0)` auf Position 5 vom Dateianfang her gerechnet gesetzt. Anschließend werden die 13 Zeichen der ISBN-Nummer mit read eingelesen. Zur Kontrolle gibt das Script im Beispiel die eingelesenen Daten aus.

### Beachten Sie:

Die Funktion `seek` können Sie nur in Verbindung mit `read` oder write verwenden, nicht in Verbindung mit sysread oder syswrite. Benutzen Sie in diesem Fall die Funktion sysseek.

## seekdir - Verzeichniszeiger positionieren

Positioniert den Verzeichniszeiger eines Verzeichnishandles, das zuvor mit opendir erzeugt wurde, auf einen beliebigen Eintrag innerhalb des Verzeichnisses. Voraussetzung dazu ist, dass die Funktion telldir angewendet wird, um die internen Positionsnummern der Verzeichniseinträge zu ermitteln.

Erwartet als Parameter:
1. das Verzeichnishandle, das bei `opendir` vergeben wurde.
2. die interne Positionsnummer eines Verzeichniseintrags, auf den positioniert werden soll. Diese interne Positionsnummern können nur durch Aufruf der Funktion `seekdir` ermittelt werden. Es handelt sich vom Dateisystem des Rechners gelieferte Adressen, also nicht um einfache fortlaufende Nummern!

### Beispiel eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI::Carp qw(fatalsToBrowser);

    my $Verzeichnis = "/usr/texte";
    opendir(DIR, $Verzeichnis) || die "$Verzeichnis: $!";
    my @Positionen;
    my @Eintraege;
    for(my $i=0;$i<10;$i++) {
      $Eintraege[$i] = readdir(DIR);
      $Positionen[$i] = telldir(DIR);
    }
    print "Content-type: text/html\n\n";
    print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
    print "<html><head><title>Testausgabe</title></head><body>\n";
    for(my $i=0;$i<10;$i++) {
      print "<p>Eintraege[$i] = $Eintraege[$i]<br>\n";
      print "Positionen[$i] = $Positionen[$i]</p>\n";
    }
    seekdir(DIR, $Positionen[5]);
    my $Eintrag = readdir(DIR);
    print "<p>Positioniert auf Positionen[5] und Eintrag gelesen: $Eintrag</p>\n";
    print "</body></html>\n";
    closedir(DIR);

### Erläuterung:

Das Beispiel leistet nichts Produktives, es dient nur zur Verdeutlichung und dazu, das Prinzip der internen Positionsnummern zu verstehen. In dem Beispiel wird ein Verzeichnis mit opendir geöffnet. Die ersten zehn Einträge des Verzeichnisses werden danach in einer for-Schleife mit readdir eingelesen. Dabei werden auch die Positionsnummern der eingelesenen Einträge gespeichert, und zwar in dem Array `@Positionen`. Das CGI-Script gibt zur Kontrolle die zehn eingelesenen Einträge und deren ermittelte Positionsnummern aus. Um die Funktion `seekdir` zu testen, wird auf eine der ermittelten Positionsnummern (`$Positionen[5]`) positioniert. Der nächste Verzeichniseintrag wird noch mal eingelesen und zur Kontrolle ausgegeben.

### Beachten Sie:

Wenn Sie mit `seekdir` auf einen Verzeichniseintrag positionieren und dann `readdir` anwenden, wird nicht derjenige Verzeichniseintrag eingelesen, auf den Sie positioniert haben, sondern der nächste!

## select - Ein-/Ausgabekanal auswählen

Wählt den Default-Ein-Ausgabekanal für nachfolgende Lese-/Schreiboperationen aus.

Erwartet als Parameter:
1. das Handle des gewünschten Ein-/Ausgabekanals. Es kann sich um ein Handle einer zuvor mit open geöffneten Datei handeln, oder um einen der Standardkanäle.

### Beispiel eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI::Carp qw(fatalsToBrowser);

    print "Content-type: text/plain\n\n";

    open(DATEI, ">>/usr/webconfig/users.txt") || die "$!";
    my $User = "Stefan";
    select(DATEI);
    print "\nuser=$User";
    close(DATEI);

    select(STDOUT);
    print "$User in Datei geschrieben";

### Erläuterung:

Im Beispiel wird zunächst ein HTTP-Header für reinen Text an den Browser gesendet. Die `print`-Funktion schreibt dabei erst mal auf den Standardausgabekanal. Anschließend wird eine Datei zum anhängenden Schreiben geöffnet. Dabei wird das Handle mit dem Namen `DATEI` erzeugt. Anschließend wird dieses Handle mit `select(DATEI)` als das aktive Handle ausgewählt. Die nachfolgende print-Funktion bezieht sich dadurch automatisch auf das ausgewählte Handle. Um in die Datei zu schreiben, ist also:
`select(DATEI);
print "\nuser=$User";`
gleichbedeutend mit: `print DATEI "\nuser=$User";`.

Nachdem die neue Zeile in die Datei geschrieben und diese geschlossen wurde, wird - wiederum mit `select` - der Standardausgabekanal `STDOUT` als neuer aktiver Kanal ausgewählt. Der nachfolgende `print`-Befehl, der eine Bestätigung an den Browser sendet, funktioniert nur, weil zuvor `STDOUT` als aktiver Kanal ausgewählt wurde. Andernfalls wäre der aktive Kanal undefiniert, da der zuvor als aktiv ausgewählte Kanal `DATEI` mittlerweile geschlossen wurde.

## sysopen - Datei ssystemnah öffnen

Öffnet eine Datei ebenso wie open. Während `open` jedoch die bequeme Art der Umleitung (mit >,>>,<, ...) an der Kommandozeile nachahmt, wird bei `sysopen` direkt der betriebssystemeigene Befehl zum Öffnen einer Datei benutzt. Der Vorteil ist, dass Sie genauer angeben können, wie Sie die Datei öffnen wollen. Der Nachteil ist, dass es Probleme mit Betriebssystemen gibt, die nicht alle Features unterstützen. Das Perl-Script lässt sich dann möglicherweise nicht mehr in verschiedenen Umgebungen ausführen.

Erwartet als Parameter:
1. den Namen des Datei-Handles (frei wählbar),
2. den Namen der Datei, wenn erfoderlich mit relativem oder absolutem Pfadnamen,
3. den Modus, in dem die Datei geöffnet werden kann. Dazu ist es ratsam, das Standardmodul `fcntl` einzubinden, in dem Konstanten für erlaubte Werte definiert sind. Folgende Konstanten sind dann erlaubt:
`O_RDONLY` bedeutet: Datei nur zum Lesen öffnen,
`O_WRONLY` bedeutet: Datei nur zum Schreiben öffnen,
`O_RDWR` bedeutet: Datei zum Lesen und Schreiben öffnen.
Diese Konstanten können Sie durch bitweises Oder (einfacher Senkrechtstrich `|`) mit folgenden Zusatzkonstanten verknüpfen: `O_APPEND` bedeutet: Schreiben nur am Ende der Datei,
`O_CREAT` bedeutet: Datei in jedem Fall neu erzeugen,
`O_EXCL` bedeutet: Datei nur dann neu erzeugen, wenn sie bislang noch nicht existiert,
`O_SYNC` bedeutet: nach jedem Schreibvorgang wird die Synchronisationsfunktion `fsync()` aufgerufen,
`O_TRUNC` bedeutet: die existierende Datei wird auf 0 Byte gekürzt, ohne gelöscht zu werden.
4. (optional) eine Angabe für die Zugriffsrechte, mit denen die Datei geöffnet werden soll. Die Angabe ist dabei die unter Unix übliche Bezeichnung der Zugriffsrechte für Welt, Gruppe und Eigner in Oktalschreibweise mit führender 0 (z.B. `0440`) und nicht in Anführungszeichen notieren.

Wenn die Datei geöffnet werden kann, gibt die Funktion den Wert `true` zurück, andernfalls den Wert `false`.

### Beispiel:

    #!/usr/bin/perl -w

    use strict;
    use Fcntl;
    my $Datei = "/usr/geistesblitze/aktuell.txt";
    sysopen(DATEI, $Datei, O_WRONLY | O_APPEND, 0440) || die "$Datei: $!";
    print DATEI "Neugier killte die Katze\n";
    close(DATEI);

### Erläuterung:

Im Beispiel wird eine Textdatei mit `sysopen` geöffnet. Dabei wird bestimmt, dass die Datei nur zum Schreiben geöffnet wird, und zwar so, dass geschriebene Inhalte an die vorhandene Datei angehängt werden (erreicht durch bitweise Verknüpfung von `O_APPEND`). Mit `print` wird ein Satz in die Datei geschrieben. Anschließend wird die Datei geschlossen. Dazu können Sie die übliche Funktion close verwenden.

### Beachten Sie:

Der Befehl `use Fcntl` zu Beginn ist erforderlich, um Zugriff auf die Konstanten wie `O_WRONLY` und `O_APPEND` zu haben.

Bei Angaben wie `O_APPEND` oder `O_CREAT` kann es sinnvoll sein, den `sysopen`-Befehl davon abhängig zu machen, ob die Datei existiert, denn anders als `open` legt `sysopen` die Datei nicht automatisch an oder überschreibt sie einfach. Die Prüfung kann durch einen Dateitest geschehen oder besser, durch die Angabe des entsprechenden Modus beim Öffnen.

## sysread - bestimmte Anzahl Zeichen systemnah lesen

Liest eine anzugebende Anzahl Zeichen aus einer Datei ab der aktuellen Position des Dateizeigers in einen Skalar ein. Die Datei sollte in den meisten Fällen sinnvollerweise mit sysopen geöffnet worden sein. Ansonsten gelten für `sysread` die gleichen Regeln zum Aufruf und beim Rückgabewert wie bei read.

## sysseek - Dateizeiger systemnah positionieren

Positioniert den Dateizeiger eines Dateihandles, das zuvor sinnvollerweise mit sysopen erzeugt wurde, an eine beliebige Stelle innerhalb der Datei. Ansonsten gelten für `sysseek` die gleichen Regeln zum Aufruf und beim Rückgabewert wie bei seek.

## syswrite - bestimmte Anzahl Zeichen systemnah schreiben

Schreibt eine anzugebende Anzahl Zeichen aus einer ebenfalls anzugebenden Variablen ab der aktuellen Position innerhalb dieser Variablen in eine Datei. Die Datei sollte in den meisten Fällen sinnvollerweise mit sysopen geöffnet worden sein.

Erwartet als Parameter:
1. das Datei-Handle.
2. einen Skalar, der die Zeichen zum Schreiben in die Datei enthält.
3. (optional) die Anzahl der in die Datei zu schreibenden Zeichen.
4. (optional) Offset - wenn die zu schreibenden Zeichen in dem Zeichenkettenskalar (2.) nicht ab dem ersten Zeichen beginnen, sondern ab einem Zeichen n, können Sie n als Offset angeben (die Zählung beginnt bei 0).

Wenn der Skalar mehr Daten enthält als geschrieben werden sollen, werden trotzdem nur so viele Zeichen geschrieben wie angegeben. Wenn der Skalar weniger Daten enthält als geschrieben werden sollen, werden nur so viele Zeichen geschrieben, wie der Skalar ab dem Offset noch enthält. Wenn Sie keine Anzahl zu schreibender Zeichen angeben, wird der komplette Inhalt des Skalars in die Datei geschrieben.

`syswrite` gibt die Anzahl tatsächlich geschriebener Zeichen zurück. Im Fehlerfall wird `undef` zurückgegeben.

### Beispiel:

    #!/usr/bin/perl

    use strict;
    use Fcntl;
    my $Datei = "/usr/bin/mycodes/mysecret.sys";
    my $Daten = "sdclknavaoertoerigjvimfvlkmdfghjdfbjdfihgjsobijsngohijsrotigueiufgulvbdkjbndfkhv";
    my $Block = 8;
    sysopen(DATEI, $Datei, O_WRONLY | O_EXCL) || die "$Datei: $!";
    for(my $i=0;$i<10;$i++) {
      my $Offset = $i * $Block;
      syswrite(DATEI,$Daten,$Block,$Offset);
    }
    close(DATEI);

### Erläuterung:

Das Beispiel schreibt eine Zeichenkette, die in `$Daten` gespeichert ist, blockweise in eine Datei. Dazu stehen die Aufrufe von `sysread` in einer for-Schleife. Die Schleife hat 10 Durchläufe, da die Länge von `$Daten` 80 Zeichen beträgt, und pro Schreibvorgang 8 Zeichen (in dem Skalar `$Block` definiert) geschrieben werden sollen. Dabei ist es wichtig, jedesmal den Offset neu zu berechnen, damit immer die jeweils nächsten 8 Zeichen geschrieben werden, und nicht immer wieder nur die ersten 8.

### Beachten Sie:

Das Beispiel selbst ist in dieser Form nicht besonders praxisrelevant, denn bei der kleinen Datenmenge empfiehlt es sich, den gesamten Inhalt von `$Daten` in einem Rutsch in die Datei zu schreiben. Aber das Prinzip lässt sich beispielsweise anwenden, wenn die Datenmenge aus anderen Quellen dynamisch gewonnen wird, sehr groß sein kann.

## tell - Position des Dateizeigers ermitteln

Ermittelt die aktuelle Byteposition des Dateizeigers eines Dateihandles, das zuvor mit open erzeugt wurde.

Erwartet als Parameter:
1. das Datei-Handle.

Gibt die aktuelle Byteposition zurück. Wenn ein Fehler aufgetreten ist, wird `-1` zurückgegeben.

### Beispiel eines vollständigen CGI-Scripts in Perl:

    #!/usr/bin/perl -w

    use strict;
    use CGI::Carp qw(fatalsToBrowser);

    my $Datei = "/usr/info/readme.txt";
    my @Zeilenanfaenge = "";
    open(DATEI, "<$Datei") || die "$Datei: $!";
    $Zeilenanfaenge[0] = tell(DATEI);
    my $i = 0;
    while(<DATEI>) {
       $i++;
       $Zeilenanfaenge[$i] = tell(DATEI);
    }
    close(DATEI);
    $i = 1;
    print "Content-type: text/html\n\n";
    print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
    print "<html><head><title>Testausgabe</title></head><body>\n";
    foreach (@Zeilenanfaenge) {
       print "Zeile $i beginnt in der Datei bei Offset $_<br>\n";
       $i++;
    }
    print "</body></html>\n";

### Erläuterung:

Das Beispiel öffnet mit `open` eine Textdatei und liest sie in einer while-Schleife zeilenweise ein. Dabei wird direkt nach dem Öffnen und bei jedem Schleifendurchgang die aktuelle Position des Dateizeigers mit `tell` ermittelt und im jeweils nächsten Element des Arrays `@Zeilenanfaenge` gespeichert. Anschließend wird HTML-Code an den Browser gesendet. Dabei werden die gespeicherten Offset-Positionen der Zeilenanfänge in einer foreach-Schleife ausgegeben.

## telldir - Position des Verzeichniszeigers ermitteln

Ermittelt die interne Positionsnummer des Verzeichniseintrags, auf dem der Verzeichniszeiger eines Verzeichnishandles steht, das zuvor mit opendir erzeugt wurde.

Erwartet als Parameter:
1. das Verzeichnishandle, das bei `opendir` vergeben wurde.

### Beispiel mit Erläuterung:

Ein vollständiges Beispiel mit Erläuterung der zusammenhängenden Funktionen `telldir` und `seekdir` wird bei der Funktion seekdir behandelt!

## write - formatierte Daten schreiben

Diese Funktion dient dazu, um Daten, die mit format formatiert wurden, datensatzweise in eine Datei zu schreiben, die zuvor mit open geöffnet wurde. Beispiele werden im Zusammenhang mit der Funktion `format` beschrieben.

| Funktionen für Datei- und Verzeichnismanagement
| Funktionen für Datum und Uhrzeit

© 2001 selfhtml@teamone.de