Dateien (1) Datenströme Standardbibliothek bietet sogenannte Datenströme (engl. Streams) Objekte, in die Informationen geschrieben oder von denen Daten gelesen werden können Zum Arbeiten mit Dateien benötigt man einen Strom, über den Ein- und Ausgaben sowie Positionsangaben realisiert werden Standardbibliothek bietet nur Datenströme, betriebssystemabhängig kann es auch noch weitere Möglichkeiten geben Gepufferte und ungepufferte Ströme Gepufferte Datenströme werden erst geschrieben, wenn genug Daten für einen ganzen Block vorhanden sind ( write back ) Ungepufferte Datenströme werden immer sofort geschrieben ( write through ) Hier: nur Betrachtung gepufferter Ströme
Dateien (2) Datenströme Einige Ströme sind immer geöffnet Standard-Strom stdout stdin stderr Standard-Strom für die Ausgabe Standard-Strom für die Eingabe Standard-Strom für Fehlermeldungen printf, scanf verwenden implizit stdout bzw. stdin Stderr wird für Fehlermeldungen verwendet Unter unixoiden Betriebssystemen sehr sinnvoll, da Datenströme umgelenkt und gefiltert werden können
Dateien (3) Öffnen und Schließen von Datenströmen Ströme werden durch Filehandler repräsentiert: Objekte des Typs FILE Dieses Objekt ist Argument für die Dateioperationen Technisch realisiert durch Zeiger auf Filehandle Filehandle wird vom Betriebssystem verwaltet Wenn Arbeit mit Strom beendet, muss er geschlossen werden Freigabe der Datei Filehandle danach ungültig Beispiel: FILE *datei; datei = fopen("beispiel.txt", "r"); //... // Hier kann der Strom // >datei< verwendet werden. //... fclose(datei); Grundlegende Funktionen Funktion fopen (s, m) fclose(f) fflush(f) Öffnet die Datei s mit dem Modus m und gibt einen Strom F zurück Schließt den Strom F Leert den Strom F
Dateien (4) Öffnen und Schließen von Datenströmen Grundlegende Funktionen Funktion fopen (s, m) fclose(f) fflush(f) Öffnet die Datei s mit dem Modus m und gibt einen Strom F zurück Schließt den Strom F Leert den Strom F fopen öffnet eine Datei: Name ist Parameter liefert Zeiger auf Filehandle zurück, bei Fehler 0 Pfadangabe ist zulässig für Dateiname fclose löst die Verknüpfung zur Datei liefert 0 zurück, wenn ordnungsgemäß ausgeführt fflush sorgt für das Schreiben gepufferter Daten in die Datei liefert 0 zurück, wenn ordnungsgemäß ausgeführt
Dateien (5) Öffnen und Schließen von Datenströmen Unterstützte Modi Modus "r" "r+" "w" "w+" "a" "a+" Öffnen zum Lesen Öffnen zum Lesen und Schreiben Öffnen zum Schreiben. Eine eventuell vorhandene Datei wird überschrieben Öffnen zum Lesen und Schreiben, sonst wie "w" Öffnen zum Schreiben. Ist die Datei vorhanden, wird angehängt Öffnen zum Lesen und Schreiben. Sonst wie "a".
Dateien (6) Öffnen und Schließen von Datenströmen Beispiel mit Fehlerausgabe #include <stdio.h> main() { FILE *datei; if ((datei = fopen("beispiel.txt", "w"))) { //... fclose(datei); } else printf("fehler beim Offnen der Datei!\n"); } // end main
Dateien (7) Ein- und Ausgabe Funktionen für binäres Lesen und Schreiben Funktion fread (b, g, n, F) fwrite(b, g, n, F) Liest n Elemente der Größe g Byte aus F und speichert sie in b Schreibt n Elemente der Größe g Byte von b nach F b Puffer beliebigen Typs mit Größe von mindestens n mal g Byte F Filehandle Binär gelesene und geschriebene Strukturen dürfen keine Zeiger enthalten, da Adressen nur im laufenden Programm Aktualität besitzen Funktionen liefern Anzahl erfolgreich gelesener bzw. Geschriebener Elemente zurück Im Fehlerfall 0 oder ganze Zahl kleiner n
Dateien (8) Ein- und Ausgabe Beispiel zum binären Schreiben von Daten und Abfangen von Dateifehlern #include <stdio.h> main() { typedef struct Adresse_s Adresse_t; struct Adresse_s { char name[30]; // Name der Person long plz; // Postleitzahl char ort[20]; // Wohnort char strasse[50]; // Straße long nummer; // Hausnummer }; Adresse_t Adressbuch[] = { //... Musikeradressliste aus Kapitel Strukturen };
Dateien (9) Ein- und Ausgabe Fortsetzung Beispiel #define ADRESSBUCH_LEN sizeof(adressbuch) / sizeof(adresse_t) FILE *datei; // Öffnen der Datei zum Schreiben if ((datei = fopen("adressen", "w"))) // Das "=" ist hier Absicht { // Schreiben des Datensatzes if (fwrite(adressbuch, sizeof(adresse_t), ADRESSBUCH_LEN, datei) < ADRESSBUCH_LEN) fprintf(stderr, "Daten konnten nicht geschrieben werden\n"); fclose(datei); } else fprintf(stderr, "Fehler beim Öffnen der Datei\n"); } // end main
Dateien (10) Ein- und Ausgabe Außer der sequenziellen Verarbeitung kann man auch gezielt auf bestimmte Positionen in der Datei zugreifen Funktion fseek(f, n, p) ftell(f) Setzt die Position in F auf n Bytes relativ zu p Liefert die aktuelle Position in Bytes relativ zum Dateianfang von F Schreib / Leseposition kann mit fseek gesetzt werden n kann in stdio.h definierte Werte zur Positionsangabe haben: SEEK_SET relativ zum Dateianfang SEEK_CUR relativ zur aktuellen Position SEEK_END relativ zum Dateiende fseek und ftell geben -1 zurück, falls ein Fehler aufgetreten ist