9. Arbeiten mit Dateien

9.1 Grundlagen
9.2 Öffnen und Schließen von Dateien
9.3 Datei Ein-/Ausgabe

9.1 Grundlagen

Alle bisher besprochenen Programme waren lediglich in der Lage, von der Konsole (Tastatur bzw. Bildschirm) zu Lesen bzw. zu Schreiben. Aber unter UNIX (auch unter MS-DOS ab Version 2.0) ist eine Umleitung dieser Standard Ein-/Ausgabe möglich. Die Umleitung bezieht sich auf die Aufrufe der Funktionen getchar, putchar, printf und scanf.

Eine Umleitung der Standard Ein-/Ausgabe erfolgt mit den Umleitungssymbolen <, > und >> bzw. durch Pipe Bildung mit | beim Aufruf des Programmes.

Beispiele:

prog1                 /* prog1 liest von Tastatur und
                         schreibt auf Bildschirm */
prog1 >hugo           /* prog1 liest von Tastatur und
                         schreibt auf Datei hugo, die neu
                         angelegt wird */
prog1 <steuer         /* prog1 liest von Datei steuer und
                         schreibt auf Bildschirm */
prog1 <steuer >>hugo  /* prog1 liest von Datei steuer und
                         schreibt auf Datei hugo weiter */
prog1|prog2           /* prog1 liest von Tastatur und gibt
                         Ausgabedaten an prog2 weiter
                         prog2 liest Daten von prog1
                         und schreibt auf Bildschirm */

Die Umleitung erfolgt transparent, d.h. das Programm merkt nichts davon; die Umleitungsangaben tauchen auch nicht in argv auf.

Beim Arbeiten mit Dateien muß die Include-Datei stdio.h dazugeladen werden. Dies erreicht man mittels

#include <stdio.h>

stdio.h enthält wichtige Definitionen von Konstanten und einer Struktur für den Dateizugriff.

Zurück zum Inhaltsverzeichnis

9.2 Öffnen und Schließen von Dateien

Natürlich kann man von einem C Programm aus auch auf jede beliebige Datei zugreifen. Für diese Zugriffe muß die Datei geöffnet und nach Abschluß der Dateiarbeiten wieder geschlossen werden. Zur Identifizierung einer Datei dient dabei ein sogenannter Filepointer, der beim erfolgreichen Öffnen der Datei als Wert der Öffnungsfunktion zurückgegeben wird.

Der Filepointer ist ein Zeiger auf eine Struktur, die Angaben über den Bearbeitungszustand der Datei enthält. Die Einzelheiten dieser Struktur, die in stdio.h definiert ist, sind für uns nicht wichtig. Die Vereinbarung:

FILE  *fp, *fopen();

definiert fp als einen Zeiger auf die Struktur FILE und fopen() als eine Funktion, die ein solches Resultat (einen Pointer auf eine Struktur FILE) liefert.

Eine Datei wird mittels

fp = fopen(name,mode);

geöffnet. name ist der Dateiname (genauer Pfadname, Achtung Sonderbedeutung von Backslash in C!) als Zeichenkette und mode kann die Werte "r" (Lesezugriff), "w" (Schreibzugriff) und "a" (anfügender Schreibzugriff) haben. Nach erfolgreichem Öffnen der Datei wird von fopen ein Zeiger auf eine Dateistruktur zurückgeliefert, ansonsten der Wert NULL (wie EOF in stdio.h definiert). War die Datei nicht schon vorhanden, so wird sie angelegt, allerdings nur bei Schreibzugriff (Das Lesen von nicht existierenden Dateien ist natürlich ein Fehler).

Eine geöffnete Datei wird bei Programmende oder -abbruch mit exit() automatisch geschlossen. Dies ist insbesondere bei Schreibzugriffen wichtig, da nur dann der Restpuffer auch wirklich in die Datei gelangt. Generell sollte man aber jede nicht mehr benötigte Datei mit

fclose(fp);

wieder schließen. fp muß dabei ein vorher von fopen() zurückgebener Filepointer sein.

Die Namen stdin, stdout und stderr sind vordefinierte konstante Filepointer, die man ohne Öffnen der zugehörigen Dateien verwenden kann, da das Öffnen beim Programmstart automatisch besorgt wird. Es gilt folgende Zuordnung:

stdin   /* Standardeingabe (Tastatur) Umlenkung möglich */
stdout  /* Standardausgabe (Bildschirm) Umlenkung möglich */
stderr  /* Fehlerausgabe (Bildschirm) keine Umlenkung */

Zurück zum Inhaltsverzeichnis

9.3 Datei Ein-/Ausgabe

Zur zeichenweisen Ein-/Ausgabe von/auf eine Datei, die über einen Filepointer identifiziert wird, stehen die Routinen getc und putc zur Verfügung.

c = getc(fp);     /* Lesen wie bei getchar */
putc(c,fp);       /* Schreiben wie bei putchar */

Sonderfall:

c = getc(stdin);     /* getchar */
putc(c,stdout);      /* putchar */

Zeilenweise Ein-/Ausgabe kann mittels fgets und fputs erledigt werden.

fgets(zeile,ZEILAE,fp);

liest die nächste Eingabezeile (bis zum und einschließlich des Zeilenendezeichens) von fp in den Vektor zeile. Es werden maximal ZEILAE-1 Zeichen gelesen und zeile immer mit '\0' abgeschlossen. Funktionswert von fgets ist der Zeigerwert zeile bzw. NULL, wenn das Dateiende erreicht ist (vgl. getline() ).

fputs(zeile,fp);

schreibt den Inhalt von zeile auf die Datei fp.

Beispielprogramm P9-1.C

/* Realisierung von fgets und fputs */
#include <stdio.h>
/* hoechstens n Zeichen ueber iop einlesen */
char *fgets(char *s,int n,register FILE *iop)
{
    register int c;
    register char *cs;
    cs = s;
    while (--n > 0 && (c=getc(iop)) != EOF)
        if ((*cs++ = c) == '\n')
            break;
    *cs = '\0';
    return((c == EOF) && cs == s) ? NULL : s);
}
/* Zeichenkette s ueber iop ausgeben */
fputs(register char *s,register FILE *iop)
{
    register int c;
    while (c = *s++)
        putc(c,iop);
}

Beispielprogramm P9-2.C

/* Realisierung des cat Kommandos */
#include <stdio.h>
/* cat: Dateien nacheinander ausgeben */
main(int argc,char *argv[])
{
    FILE *fp, *fopen();
    if (argc == 1)   /* ohne Argumente */
        filecopy(stdin);   /* Standard Eingabe kopieren */
    else
        while (--argc > 0)
            if ((fp=fopen(*++argv,"r")) == NULL) {
                fprintf(stderr,
                    "cat: can't open %s\n",*argv);
                exit(1);
            } else {
                filecopy(fp);
                fclose(fp);
            }
    exit(0);
}
filecopy(fp)   /* Datei fp als Standard Ausgabe ausgeben */
FILE *fp;
{
    int c;
    while ((c=getc(fp)) != EOF)
        putc(c,stdout);
}

Für die formatierte Datei Ein-/Ausgabe werden fprintf und fscanf verwendet. Sie arbeiten genauso wie printf und scanf, haben jedoch zusätzlich als ersten Parameter den Filepointer fp.

Zurück zum Inhaltsverzeichnis