# 4.6 File Pointer

Quelle: https://inf.zone/lectures/4-memory/short-4-6-file-pointer/

## Video

[Video ansehen (1080p)](https://videos.inf.zone/e84632c4a56ea901/short-4-6-file-pointer-1080p.mp4) · [Video (720p)](https://videos.inf.zone/e84632c4a56ea901/short-4-6-file-pointer-720p.mp4) · [Video (480p)](https://videos.inf.zone/e84632c4a56ea901/short-4-6-file-pointer-480p.mp4) · [Video auf YouTube](https://youtu.be/g8jW99DfKMk)

## Hinweise zu diesem Video

**Korrekturen**

Die Korrekturen betreffen das Video. In den Folien zum Herunterladen sind sie eingearbeitet, soweit sie die Folien betreffen.

- Folien 6, 7 und 12: Das Ergebnis von fgetc muss in einer Variablen vom Typ int stehen, nicht char. Mit char endet die Schleife vorzeitig, sobald die Datei ein Byte mit dem Wert 0xFF enthält; auf Systemen, auf denen char kein Vorzeichen hat, lehnt der Compiler den Vergleich mit EOF ab.
- Ton zu Folie 4: Zum Lesen und Schreiben derselben Datei braucht man nicht zwei File Pointer. Die Modi &#34;r&#43;&#34;, &#34;w&#43;&#34; und &#34;a&#43;&#34; öffnen eine Datei für beides.

## Material

- [Folien](https://inf.zone/download/lectures/4-memory/4.6-file-pointer.pdf)
- Folien und Transkript: unten auf dieser Seite

## Folien und Transkript

*Folientext aus den PDF-Folien, darunter jeweils der gesprochene Text des Videos. Der gesprochene Text ist maschinell transkribiert und nachkorrigiert, kann aber noch Fehler enthalten; im Video sprechen abwechselnd Prof und eine AI-Figur, die Sprecherwechsel sind nicht markiert. Die Zuordnung zu den Folien ist ungefähr. Die Zeitangaben verlinken auf die Stelle im Video (YouTube). Maßgeblich sind Video und Folien.*

### Folie 1 — File Pointer

[Folie 1 als PDF](https://inf.zone/download/lectures/4-memory/4.6-file-pointer.pdf#page=1)

#### Transkript

**[Video 00:00–00:30](https://www.youtube.com/watch?v=g8jW99DfKMk&t=0)**

Dies ist Inf-Einf-B. Heute File Pointer. Hallo und herzlich willkommen zu unserem heutigen Video. Schön dich zu sehen. Bereit für eine spannende Reise in die Welt der Dateizeiger?

### Folie 2

[Folie 2 als PDF](https://inf.zone/download/lectures/4-memory/4.6-file-pointer.pdf#page=2)

Die Möglichkeit, Daten aus Dateien zu lesen und in Dateien zu schreiben, ist das wichtigste Mittel zur Speicherung persistenter Daten – Daten, die nicht verschwinden, wenn Ihr Programm beendet wird.

Die Abstraktion von Dateien, die C bereitstellt, wird in einer Datenstruktur namens FILE implementiert.

Fast immer arbeiten wir mit Pointern auf diese Dateien, FILE\*.

#### Transkript

**[Video 00:00–00:30](https://www.youtube.com/watch?v=g8jW99DfKMk&t=0)**

Natürlich. Obwohl spannend vielleicht nicht das erste Wort ist, das unseren Studierenden dabei einfällt. Na ja, für unsere Studierenden ist es auf jeden Fall wichtig. Ohne Dateizeiger keine persistente Datenspeicherung. Bisher waren die Programme, die wir geschrieben haben, ziemlich vergänglich. Sie laufen, machen etwas und dann.

**[Video 00:30–01:05](https://www.youtube.com/watch?v=g8jW99DfKMk&t=30)**

Puff, sind alle Daten weg. Genau, das werden wir heute ändern. Machen Sie sich auf ein interessantes Video gefasst. Lassen Sie uns gleich einsteigen. In C arbeiten wir mit einer speziellen Datenstruktur namens FILE, um Dateien zu verwalten. Aber was noch wichtiger ist: Wir arbeiten fast ausschließlich mit Zeigern auf diese Struktur, also FILE Stern. Wenn Sie die Vorlesungen zu Zeigern und dynamischer Speicherverwaltung gesehen haben, haben Sie dafür bereits eine gute Grundlage. Hatte ich dir nicht schon mal gesagt, dass wir Pointer statt Zeiger sagen? Oh, ja. Anscheinend habe ich deine Wünsche nicht persistent gespeichert.

**[Video 01:05–01:30](https://www.youtube.com/watch?v=g8jW99DfKMk&t=65)**

Wie passend zum Thema, nicht wahr? Ja, ja, so sind sie die Computerprogramme. Sie laufen, machen etwas und dann puff, sind alle Daten weg. Hey, das ist fies. Tja, das musst du halt aushalten.

### Folie 3 — File Pointer

[Folie 3 als PDF](https://inf.zone/download/lectures/4-memory/4.6-file-pointer.pdf#page=3)

Alle wichtigen Funktionen zur Verarbeitung von Dateien befinden sich in stdio.h.

Diese Funktionen akzeptieren FILE\* als einen ihrer Parameter – außer der Funktion fopen(), die verwendet wird, um überhaupt erst einen File Pointer zu erhalten.

Die häufigsten Ein-/AusgabeFunktionen für Dateien sind:

fopen()  fclose() fgetc()  fputc() fread()  fwrite()

#### Transkript

**[Video 01:05–01:30](https://www.youtube.com/watch?v=g8jW99DfKMk&t=65)**

Jetzt mach dich mal nützlich und leg endlich los. Ja, na gut. Alle relevanten Funktionen für die Dateiverarbeitung finden Sie in der Header-Datei stdio.h. Die meisten von Ihnen haben diese Datei vermutlich schon häufig eingebunden, da sich dort auch printf befindet.

**[Video 01:30–02:02](https://www.youtube.com/watch?v=g8jW99DfKMk&t=90)**

Wobei printf halt nur die Spitze des Eisbergs ist. Die Funktionen, die wir heute kennenlernen werden, sind deutlich spezialisierter. Fast alle erwarten einen File Pointer als Parameter, mit einer wichtigen Ausnahme fopen. Diese Funktion ist sozusagen unser Türöffner. Von ihr bekommen wir einen File Pointer. Wie wäre es denn mit einem Überblick über die Funktionen, die es gibt? Dann kannst du ja jede Funktion einzeln erklären. Natürlich. Die sechs wichtigsten Funktionen sind fopen und fclose, unser Ein- und Ausgang sozusagen. Dann fgetc und fputc für einzelne Zeichen.

**[Video 02:02–02:32](https://www.youtube.com/watch?v=g8jW99DfKMk&t=122)**

und schließlich fread und fwrite für größere Datenmengen. Wie diese im Detail funktionieren, werden wir gleich sehen. Die erste Funktion, die wir uns genauer ansehen, ist fopen.

### Folie 4 — fopen

[Folie 4 als PDF](https://inf.zone/download/lectures/4-memory/4.6-file-pointer.pdf#page=4)

Öffnet eine Datei und gibt einen File Pointer darauf zurück.

Überprüfen Sie immer den Rückgabewert, um sicherzustellen, dass Sie nicht NULL zurückbekommen.

```text
FILE* ptr = fopen(<filename>, <operation>);

FILE* ptr1 = fopen("file1.txt", "r");
FILE* ptr2 = fopen("file2.txt", "w");
FILE* ptr3 = fopen("file3.txt", "a");
```

#### Transkript

**[Video 02:02–02:32](https://www.youtube.com/watch?v=g8jW99DfKMk&t=122)**

Sie ist wie gesagt besonders wichtig, da sie uns überhaupt erst den Zugang zu einer Datei verschafft. Die Funktion gibt einen File Pointer zurück, aber Vorsicht: dieser Pointer könnte null sein. Und das ist auch gleich einer der häufigsten Anfängerfehler, also das vergisst den Rückgabewert von fopen zu überprüfen. Vergisst man die Überprüfung auf null und das Öffnen der Datei hat nicht geklappt, stürzt das Programm kurz darauf mit einem

**[Video 02:32–03:02](https://www.youtube.com/watch?v=g8jW99DfKMk&t=152)**

Segmentation fault ab, wenn es versucht, auf einen Nullpointer zuzugreifen. Die grundlegende Syntax von fopen sehen Sie hier auf der Folie. Wir übergeben den Dateinamen und die gewünschte Operation als Parameter. Was ist denn diese Operation? Vielleicht erklärst du es den Studierenden, was es für Möglichkeiten gibt. Das mache ich gerne anhand eines konkreten Beispiels auf der nächsten Folie. Lassen Sie uns das anhand konkreter Beispiele verdeutlichen. Der wichtigste Operationsmodus ist r für read, also lesen. Wenn wir eine Datei zum Lesen öffnen

**[Video 03:02–03:33](https://www.youtube.com/watch?v=g8jW99DfKMk&t=182)**

wie hier file1.txt können wir anschließend Informationen aus dieser Datei auslesen. Der zweite wichtige Modus ist w für write, also schreiben. Hier müssen Sie allerdings vorsichtig sein. Wenn Sie eine Datei im Schreibmodus öffnen und diese Datei bereits existiert, wird der gesamte bisherige Inhalt gelöscht. Es gibt dann noch einen dritten Modus, den wir gleich sehen werden. Aber zunächst noch etwas Wichtiges: Sie können nicht mit einem File Pointer, den Sie zum Lesen geöffnet haben, in die Datei schreiben und umgekehrt. Wenn Sie beides brauchen, müssen Sie zwei separate File Pointers auf dieselbe Datei öffnen.

**[Video 03:33–04:04](https://www.youtube.com/watch?v=g8jW99DfKMk&t=213)**

Der dritte wichtige Modus ist a für append, also anhängen. Der Unterschied zum write-Modus ist folgender: Beim append-Modus wird der bestehende Inhalt nicht gelöscht. Stattdessen werden neue Daten am Ende der Datei angefügt. Wenn Sie also beispielsweise eine Log-Datei haben, an die Sie bei jedem Programmstart neue Einträge anhängen möchten, ist der append-Modus die beste Wahl.

### Folie 5 — fclose

[Folie 5 als PDF](https://inf.zone/download/lectures/4-memory/4.6-file-pointer.pdf#page=5)

Schließt die Datei, auf die der übergebene File Pointer zeigt.

```text
fclose(<file pointer>);
```

#### Transkript

**[Video 03:33–04:04](https://www.youtube.com/watch?v=g8jW99DfKMk&t=213)**

Kommen wir zu fclose, dem Gegenstück zu fopen. Sobald Sie mit einer Datei fertig sind, sollten Sie sie schließen. Das ist nicht nur eine Frage guten Stils, sondern wirklich erforderlich. Ein nicht geschlossener File Pointer

**[Video 04:04–04:34](https://www.youtube.com/watch?v=g8jW99DfKMk&t=244)**

kann zu Ressourcenlecks führen. Ruft man in einem Programm oft fopen auf, ohne die Dateien wieder zu schließen, kann das im Laufe der Zeit zu einem Absturz Ihres Programms führen. Es kann aber auch andere Programme stören, weil die maximal erlaubte Anzahl offener Dateien überschritten wird. Das Betriebssystem erlaubt anderen Programmen dann nicht mehr weitere Dateien zu öffnen. Die Syntax von fclose ist denkbar einfach. Sie übergeben einfach den File Pointer an fclose. Nach dem Aufruf von fclose können Sie mit diesem File Pointer keine weiteren Operationen mehr durchführen. Wenn Sie die Datei erneut verwenden möchten

**[Video 04:34–05:14](https://www.youtube.com/watch?v=g8jW99DfKMk&t=274)**

müssen Sie sie mit fopen neu öffnen.

### Folie 6 — fgetc

[Folie 6 als PDF](https://inf.zone/download/lectures/4-memory/4.6-file-pointer.pdf#page=6)

Liest und gibt das nächste Zeichen aus der Datei zurück.

Hinweis: Der File Pointer muss im Modus "r" für Lesen geöffnet sein, sonst gibt es einen Fehler.

```text
int ch = fgetc(<file pointer>);
```

Mit fgetc() können wir, in einer Schleife verwendet, alle Zeichen aus einer Datei lesen und auf dem Bildschirm ausgeben.

Dies entspricht dem Linux-Befehl "cat".

```text
int ch;
while((ch = fgetc(ptr)) != EOF)
    printf("%c", ch);
```

#### Transkript

**[Video 04:34–05:14](https://www.youtube.com/watch?v=g8jW99DfKMk&t=274)**

Jetzt wird es interessant. Mit fgetc können wir einzelne Zeichen aus einer Datei lesen. Bei jedem Aufruf bekommen wir das nächste Zeichen oder wenn es der erste Aufruf ist, das erste Zeichen der Datei. Das gelesene Zeichen wird in einer char-Variablen gespeichert. Wie bereits erwähnt, der File Pointer muss dafür im read-Modus geöffnet sein. Versuchen Sie nicht, mit einem write-only-Pointer zu lesen. Das wird nicht funktionieren. Besonders spannend wird es, wenn wir fgetc in einer Schleife verwenden. Sehen Sie sich den Code an. Wir lesen Zeichen für Zeichen, bis wir auf EOF stoßen. Das End-of-File-Zeichen. EOF ist übrigens eine spezielle Konstante, die in stdio.h definiert ist.

**[Video 05:14–05:44](https://www.youtube.com/watch?v=g8jW99DfKMk&t=314)**

Wichtig: Das EOF-Zeichen selber steht nicht in der Datei. Dateien haben oft gar keine Markierung am Ende. Sie enden halt einfach mit irgendeinem Zeichen. Das bekommt man mit fgetc dann auch noch zurück. Und wenn fgetc dann ein weiteres Mal aufgerufen wird, muss man ja irgendwie mitgeteilt bekommen, dass man jetzt am Ende angekommen ist. Und dafür ist eben diese spezielle Konstante EOF vorgesehen. Also mit dieser einfachen Schleife haben wir praktisch den Linux-Befehl cat nachgebaut. Der einzige Unterschied ist jetzt noch, dass cat ein paar zusätzliche Features hat.

**[Video 05:44–06:01](https://www.youtube.com/watch?v=g8jW99DfKMk&t=344)**

Aber das Grundprinzip ist genau das gleiche. Nach dem Lesen kommt natürlich das Schreiben. fputc ist sozusagen das Gegenstück zu fgetc. Die Funktion nimmt zwei Parameter: das zu schreibende Zeichen und den File Pointer.

### Folie 7 — fputc

[Folie 7 als PDF](https://inf.zone/download/lectures/4-memory/4.6-file-pointer.pdf#page=7)

Schreibt oder hängt das angegebene Zeichen an die Datei an.

Hinweis: Der File Pointer muss im Modus „w“ für Schreiben oder „a“ für Anhängen geöffnet sein, sonst gibt es einen Fehler.

```text
fputc(<character>, <file pointer>);
fputc('A', ptr2);
fputc('!', ptr3);

int ch;
while((ch = fgetc(ptr)) != EOF)
    fputc(ch, ptr2);
```

#### Transkript

**[Video 05:44–06:01](https://www.youtube.com/watch?v=g8jW99DfKMk&t=344)**

Wichtig ist hier wieder der Modus. Der Pointer muss entweder für write oder append geöffnet sein.

**[Video 06:01–06:37](https://www.youtube.com/watch?v=g8jW99DfKMk&t=361)**

Im Beispiel sehen Sie zwei typische Anwendungen. Bei Pointer 2, der im Write-Modus geöffnet wurde, schreiben wir ein A. Wenn die Datei bereits Inhalt hatte, wird dieser überschrieben. Bei Pointer 3, der im Append-Modus geöffnet wurde, fügen wir ein Ausrufezeichen an. Hier bleibt der bisherige Inhalt erhalten. Mit diesen beiden Funktionen fgetc und fputc können wir übrigens auch Dateien kopieren. Statt die gelesenen Zeichen auszugeben, schreiben wir sie einfach in eine andere Datei. Das entspricht dann dem Linux-Befehl cp.

### Folie 8 — fread

[Folie 8 als PDF](https://inf.zone/download/lectures/4-memory/4.6-file-pointer.pdf#page=8)

Liest \<qty\> Einheiten der Größe \<size\> aus der Datei und speichert sie im Puffer (meist ein Array), auf den \<buffer\> zeigt.

Hinweis: Der File Pointer muss im Modus „r“ geöffnet sein.

```text
fread(<buffer>, <size>, <qty>, <file pointer>);

int arr[10];
fread(arr, sizeof(int), 10, ptr);
double* arr2 = malloc(sizeof(double) * 80);
fread(arr2, sizeof(double), 80, ptr);
char c;
fread(&c, sizeof(char), 1, ptr);
```

#### Transkript

**[Video 06:01–06:37](https://www.youtube.com/watch?v=g8jW99DfKMk&t=361)**

Sie sehen also: die grundlegenden Dateioperationen in Unix sind im Prinzip sehr einfache Programme. Sie nutzen genau die Funktionen, die wir hier besprechen.

**[Video 06:37–07:08](https://www.youtube.com/watch?v=g8jW99DfKMk&t=397)**

Jetzt wird es etwas komplexer. fread ist die effizientere Variante von fgetc. Statt einzelner Zeichen können wir hier beliebig große Datenblöcke auf einmal lesen. Die Funktion erwartet vier Parameter: einen Pointer auf den Speicherbereich, in den gelesen werden soll, die Größe jeder Einheit, die Anzahl der Einheiten und natürlich den File Pointer. Im ersten Beispiel lesen wir zehn Integers. Wir haben ein Array mit zehn Plätzen und lesen genau diese Menge. sizeof int gibt uns die Größe eines Integers, typischerweise vier Bytes. Also lesen wir insgesamt vierzig Bytes aus der Datei.

**[Video 07:08–07:33](https://www.youtube.com/watch?v=g8jW99DfKMk&t=428)**

Im zweiten Beispiel wird es noch interessanter. Hier allozieren wir dynamischen Speicher für 80 Doubles. Ein Double ist normalerweise 8 Bytes groß, also reservieren wir 640 Bytes. Diese füllen wir dann mit fread. Der Pointer arr2 zeigt auf den Anfang dieses Speicherbereichs. Ja, da freust du dich endlich wieder einmal über die dynamische Speicherverwaltung darfst du sprechen. Ich erinnere mich noch gut an das Pointer-Video. Ja, die gute alte Speicherverwaltung.

**[Video 07:33–08:10](https://www.youtube.com/watch?v=g8jW99DfKMk&t=453)**

Hach, ist sie nicht schön? So flexibel, so dynamisch, einfach toll. Aber heute wollten wir ja über File Pointer reden. Ein letztes Beispiel zu fread: Wenn wir nur ein einzelnes Zeichen lesen wollen, müssen wir die Adresse der Variable übergeben. Das Kaufmannsund vor der Variable c ist wichtig, denn fread erwartet einen Pointer auf den Speicherbereich, in den geschrieben werden soll. Kommen wir zu fwrite, dem Gegenstück zu fread. Die Syntax ist identisch, nur die Richtung des Datenflusses ist umgekehrt. Statt Daten aus der Datei zu lesen, schreiben wir sie in die Datei. Auch hier müssen wir wieder auf den korrekten Modus achten, entweder write oder append. Die Parameter sind die gleichen wie bei fread.

**[Video 08:10–08:48](https://www.youtube.com/watch?v=g8jW99DfKMk&t=490)**

ein Pointer auf den Speicherbereich, aus dem gelesen werden soll, die Größe jeder Einheit, die Anzahl der Einheiten und der File Pointer.

### Folie 9 — fwrite

[Folie 9 als PDF](https://inf.zone/download/lectures/4-memory/4.6-file-pointer.pdf#page=9)

Schreibt \<qty\> Einheiten der Größe \<size\> in die Datei, indem sie aus dem Puffer (meist ein Array) gelesen werden.

Hinweis: Der File Pointer muss im Modus „w“ oder „a“ geöffnet sein.

```text
fwrite(<buffer>, <size>, <qty>, <file pointer>);
int arr[10];
fwrite(arr, sizeof(int), 10, ptr);
double* arr2 = malloc(sizeof(double) * 80);
// … arr2 befüllen …
fwrite(arr2, sizeof(double), 80, ptr);
```

#### Transkript

**[Video 08:10–08:48](https://www.youtube.com/watch?v=g8jW99DfKMk&t=490)**

Es ist im Prinzip wie ein Kopiervorgang. Sie sagen der Funktion, nimm diese Menge an Daten von dieser Stelle und schreibe sie in die Datei. Die Beispiele für fwrite sind analog zu denen von fread. Im ersten Fall schreiben wir zehn Integers aus einem Array in eine Datei. Das sind wieder vierzig Bytes, wenn ein Integer vier Bytes groß ist. Im zweiten Beispiel sehen wir wieder dynamisch allozierten Speicher. Wir schreiben achtzig Doubles, also sechshundertvierzig Bytes in die Datei. Natürlich müssen die Daten in arr2 vorher mit sinnvollen Werten gefüllt worden sein. Ein wichtiger Hinweis zur Effizienz.

**[Video 08:48–09:04](https://www.youtube.com/watch?v=g8jW99DfKMk&t=528)**

Wenn Sie größere Datenmengen verarbeiten, sind fread und fwrite deutlich effizienter als fgetc und fputc. Bei einzelnen Zeichen macht der Unterschied kaum etwas aus.

### Folie 10 — Weitere nützliche Funktionen aus stdio.h

[Folie 10 als PDF](https://inf.zone/download/lectures/4-memory/4.6-file-pointer.pdf#page=10)

Funktion Beschreibung

fgets Liest einen kompletten String aus einer Datei.

fputs Schreibt einen kompletten String in eine Datei.

fprintf Schreibt einen formatierten String in eine Datei.

fseek Ermöglicht Vor- und Zurückspulen innerhalb einer Datei.

ftell Gibt die aktuelle (Byte-)Position in der Datei an.

feof Zeigt an, ob das Dateiende erreicht wurde.

ferror Zeigt an, ob ein Fehler aufgetreten ist.

#### Transkript

**[Video 08:48–09:04](https://www.youtube.com/watch?v=g8jW99DfKMk&t=528)**

Aber stellen Sie sich vor, Sie müssen eine Datei mit mehreren Megabyte verarbeiten. Da summiert sich der Overhead.

**[Video 09:04–09:39](https://www.youtube.com/watch?v=g8jW99DfKMk&t=544)**

der einzelnen Funktionsaufrufe. Was uns schon fast zum letzten Teil der Vorlesung bringt, oder? Zum Abschluss möchte ich Ihnen noch einen Überblick über weitere nützliche Funktionen geben, die Sie in der Headerdatei stdio finden. Diese werden Ihnen früher oder später in der Praxis begegnen. fgets und fputs sind die String-Versionen von fgetc und fputc. Sie arbeiten mit ganzen Zeichenketten statt einzelnen Zeichen. fprintf ist wie printf, schreibt aber in eine Datei statt auf den Bildschirm. Besonders interessant ist fseek. Denken Sie an einen Kassettenrekorder. Sie können damit in der Datei vor- und zurückspulen oder an eine bestimmte Stelle springen.

**[Video 09:39–10:10](https://www.youtube.com/watch?v=g8jW99DfKMk&t=579)**

ftell sagt Ihnen dann, an welcher Position Sie sich gerade befinden.

### Folie 11

[Folie 11 als PDF](https://inf.zone/download/lectures/4-memory/4.6-file-pointer.pdf#page=11)

E X T R A S I N 3 M I N U T E N FRAGEN – ANTWORTEN – RÄTSEL UND KURZE ZUSAMMENFASSUNG

#### Transkript

> Zuordnung unsicher: wenige gemeinsame Textmerkmale; anhand der benachbarten Folien eingeordnet.

**[Video 09:39–10:10](https://www.youtube.com/watch?v=g8jW99DfKMk&t=579)**

Kassettenrekorder, ernsthaft.

### Folie 12

[Folie 12 als PDF](https://inf.zone/download/lectures/4-memory/4.6-file-pointer.pdf#page=12)

Was fehlt hier?

```text
FILE* fp = fopen("daten.txt", "r");
int c;
while((c = fgetc(fp)) != EOF) {
    printf("%c", c);
}
```

#### Transkript

**[Video 09:39–10:10](https://www.youtube.com/watch?v=g8jW99DfKMk&t=579)**

Vielleicht sollten wir beim nächsten Mal ein moderneres Beispiel verwenden. Ja, dann halt ein DVD-Player. Mit fseek kann man quasi einstellen, in welcher Spur der Laser lesen soll. Nicht hilfreich. Ja, dann kann ich dir auch nicht helfen. Ich mache mal weiter. feof und ferror sind wichtige Hilfsfunktionen für die Fehlerbehandlung. Mit feof prüfen Sie, ob Sie das Dateiende erreicht haben. Und ferror zeigt Ihnen an, ob etwas schiefgelaufen ist.

**[Video 10:10–10:37](https://www.youtube.com/watch?v=g8jW99DfKMk&t=610)**

So, ich würde ja jetzt abmoderieren, aber ich kann mich dunkel erinnern, dass am Ende des Videos immer noch irgendetwas kommt. Ich muss mir echt mal eine persistente Speicherlösung bauen. Wie hieß der Teil dann gleich nochmal? Es war irgendso was wie Spoiler-Alert, die drei häufigsten Klausuraufgaben, oder? Nein, darüber sprechen wir, wenn die Kamera dann nicht mehr läuft. Wir haben immer die drei extra Minuten gemacht. Erinnerst du dich wirklich nicht mehr daran? Mit Rätseln, Wiederholungsfragen und weiteren Klarstellungen.

**[Video 10:37–11:11](https://www.youtube.com/watch?v=g8jW99DfKMk&t=637)**

Weißt du es echt nicht mehr? Doch klar. Genau das habe ich doch gerade eben auch gesagt. Du musst mir schon zuhören. Also, auch heute machen wir wieder die drei extra Minuten, so wie im letzten Video und im Video davor. Also so wie immer halt. Was gibt's jetzt da so zu schauen? Pa, ich weiß genau, was wir da immer gemacht haben. Jawohl. Also, ich fange jetzt einfach an. Also, ich habe hier gleich einmal eine einfache, aber wichtige Frage. Was fehlt in diesem Codebeispiel? Es sieht auf den ersten Blick korrekt aus. Wir öffnen eine Datei, lesen sie Zeichen für Zeichen und geben den Inhalt aus. Hier ist die Lösung.

**[Video 11:11–11:46](https://www.youtube.com/watch?v=g8jW99DfKMk&t=671)**

Willst du den Studierenden nicht vielleicht erst einmal etwas Zeit geben, das Programm anzuschauen, so wie wir das halt immer machen? Ja, klar, aber natürlich halten Sie das Video also hier kurz an. Ich bin dann gleich mit der Lösung zurück. Also die Antwort ist, es fehlt etwas, und zwar nicht nur eine, sondern gleich zwei Sachen. Erstens, wir haben kein fclose am Ende. Daran haben Sie wahrscheinlich sofort gedacht. Aber das ist nicht alles. Was fehlt denn noch?

**[Video 11:46–12:02](https://www.youtube.com/watch?v=g8jW99DfKMk&t=706)**

Na, sehen Sie es? Es fehlt halt auch noch die Überprüfung, ob fopen erfolgreich war, also ob fp nicht null ist. Beides sind wichtige Schritte, die wir uns vorhin angeschaut haben. Genau die Art von Details, die den Unterschied zwischen funktionierendem und robustem Code ausmachen.

**[Video 12:02–12:33](https://www.youtube.com/watch?v=g8jW99DfKMk&t=722)**

Ich habe heute auch was vorbereitet. Jetzt wird es etwas anspruchsvoller. Hier sehen Sie ein typisches Muster für das effiziente Einlesen größerer Dateien. Statt einzelner Zeichen lesen wir jetzt immer Blöcke von 1024 Bytes ein. Kannst du vielleicht kurz erklären, warum das effizienter ist? Natürlich. Aber hihi. Willst du den Studierenden nicht vielleicht erst einmal etwas Zeit geben, das Programm anzuschauen, so wie wir das halt immer machen? Ah, das ist jetzt die Retourkutsche, ja? Na gut, halten Sie das Video hier am besten kurz an.

**[Video 12:33–13:05](https://www.youtube.com/watch?v=g8jW99DfKMk&t=753)**

Warum ist das gezeigte Vorgehen effizient? So, jeder Funktionsaufruf verursacht einen gewissen Aufwand. Es muss ja zum Beispiel für den Aufruf ein Stackframe angelegt werden. Und bei den Funktionen, die wir uns angeschaut haben, muss das Programm auch noch in den Kernel des Betriebssystems springen. Da liegt der Code von solchen Systemfunktionen. Die nennt man übrigens auch Systemcalls. Aber das ist jetzt nicht wichtig. Jedenfalls hat jeder Aufruf einen gewissen Overhead. Wenn wir eine Datei von einem Megabyte hätten einlesen wollen würden, würde das mit fgetc eine Million Funktionsaufrufe benötigen.

**[Video 13:05–13:28](https://www.youtube.com/watch?v=g8jW99DfKMk&t=785)**

Beim hier gezeigten Programm sind es stattdessen nur etwa 1000. Interessant ist auch die Variable bytes\_read. Sie zeigt uns, wie viele Bytes von fread tatsächlich eingelesen wurden. Das muss ja nicht unbedingt genau so viel sein, wie wir angefordert hatten. Warum nicht? Naja, wenn die Datei eine Länge hat, die kein Vielfaches von 1024 ist, wird der letzte Block ja kürzer sein. Das müssen wir bei der Verarbeitung berücksichtigen.

**[Video 13:28–14:03](https://www.youtube.com/watch?v=g8jW99DfKMk&t=808)**

Eine Frage, die jetzt vielleicht aufkommen könnte sein: Warum machen wir es eigentlich so kompliziert? Kann man es nicht irgendwie einfacher machen, indem man die Dateigröße ermittelt und genauso viel Speicher allokiert und dann die Datei mit einem einzigen fread-Aufruf einliest? Ah, eine ausgezeichnete Frage. Prinzipiell kann man das machen und es wird auch oft gemacht. Aber es gibt gute Gründe, warum man es oft nicht macht. Erstens: Was passiert, wenn die Datei größer ist als der verfügbare Arbeitsspeicher? Nachher muss ich wieder eine zehn Gigabyte Videodatei auf einem Rechner bearbeiten, der nur sechzehn Gigabyte RAM hat.

**[Video 14:03–14:36](https://www.youtube.com/watch?v=g8jW99DfKMk&t=843)**

Ich habe dir doch schon irgendwann einmal erklärt, dass nicht du die Videos schneidest, sondern ich. Du solltest dir echt mal ein Gedächtnis zulegen. Ja, kann sein. Aber das ist doch jetzt nicht wichtig. Nicht vom Thema ablenken. Zweitens: Selbst wenn genug RAM verfügbar ist, was wenn gerade mehrere Programme laufen, die alle gleichzeitig große Dateien verarbeiten wollen? Der Arbeitsspeicher ist eine geteilte Ressource. Drittens: Bei Streaming-Daten oder Netzwerk-Sockets kennen wir die Gesamtgröße der Daten, die wir verarbeiten, oft gar nicht im Voraus. Und viertens: Bei unserem gezeigten Programm

**[Video 14:36–15:02](https://www.youtube.com/watch?v=g8jW99DfKMk&t=876)**

können wir mit der Verarbeitung der Daten bereits beginnen, sobald der Buffer das erste Mal gefüllt ist. Das verbessert ganz erheblich die Latenz. Das ist ein wichtiges Performance-Kriterium, das besonders wichtig ist bei. Ich sehe schon, wo das hinführt. Vielleicht bleiben wir erst mal bei den Grundlagen. Natürlich, aber Buffer-Management ist einfach so ein faszinierendes Thema. Warten Sie erst, bis wir zu Ringpuffern kommen. Aber nicht mehr heute. Ich glaube, für heute haben unsere Studierenden genug zum Nachdenken. Ja, freilich.

**[Video 15:02–15:38](https://www.youtube.com/watch?v=g8jW99DfKMk&t=902)**

Damit kommen wir dann also auch schon zum Ende unserer heutigen Vorlesung. Wir haben gelernt, wie wir mit File Pointern Daten persistent speichern können, haben die wichtigsten Funktionen kennengelernt und gesehen, wie man effizient mit Buffern arbeitet. Ganz besonders faszinierend finde ich ja. Moment, bevor du jetzt noch eine Vorlesung über unterschiedliche Buffer-Strategien anfängst. Aber die Ring-Buffer-Implementierung mit mehreren Produzenten und Konsumenten ist doch wirklich elegant. Stellen Sie sich vor, damit könnten wir total gut. Danke dir. Aufhören, liebe Studierende. In den Übungen brauchen Sie wirklich nur die grundlegenden Dateioperationen. Ring Buffers kommen vielleicht irgendwann später.

**[Video 15:38–15:58](https://www.youtube.com/watch?v=g8jW99DfKMk&t=938)**

Oh, das wäre doch ein tolles Thema für die Prüfung. Hör auf jetzt. Wir sehen uns dann im nächsten Video zum Thema. Naja, irgendwas. Jedenfalls nicht Ringpuffer. Bis bald. Schau mal. Hier ist eine Klausuraufgabe zu lockfreien Ringpuffern. Dies war Inf-Einf-B.

### Folie 13 — Warum ist das effizienter als einzelne Zeichen zu lesen?

[Folie 13 als PDF](https://inf.zone/download/lectures/4-memory/4.6-file-pointer.pdf#page=13)

```text
FILE* fp = fopen("large_data.txt", "r");
if (fp == NULL) return 1;

char buffer[1024];
size_t bytes_read;
while ((bytes_read = fread(buffer, 1, sizeof(buffer), fp)) > 0) {
    // Verarbeite buffer[0] bis buffer[bytes_read-1]
    process_data(buffer, bytes_read);
}

fclose(fp);
```

#### Transkript

*Kein Transkriptabschnitt eindeutig dieser Folie zugeordnet. Möglicherweise eine Aufbau-/Grafikfolie oder eine Abweichung zwischen PDF und Video.*

### Folie 14

[Folie 14 als PDF](https://inf.zone/download/lectures/4-memory/4.6-file-pointer.pdf#page=14)

File Pointer ermöglichen persistente

Buffer-Größe dem Anwendungsfall anpassen.

Datenspeicherung.

Wichtigste Funktionen:

Auf NULL-Pointer und korrektes Schließen achten

fopen(), fclose(),

fgetc(), fputc(), fread(), fwrite()

> Bildinhalte sind nicht transkribiert; siehe Originalfolie.

#### Transkript

*Kein Transkriptabschnitt eindeutig dieser Folie zugeordnet. Möglicherweise eine Aufbau-/Grafikfolie oder eine Abweichung zwischen PDF und Video.*
