3.3. FILE: En abstrakt type

For at programmere på højt niveau i C sproget skabes abstraktioner, som kan bruges til noget nyttigt. Fx. er en fil en abstraktion, som operativsystemet leverer. En fil er en ordnet sekvens af bytes. En disk-fils bytes ligger ikke altid i en pæn, ordnet rækkefølge på disken. Operativ-systemet får det imidlertid til at se sådan ud.

Endvidere sørger Linux for, at for eksempel en seriel port ser ud som en fil, selv om den ikke er det. Man kan skrive til et serielt interface, som om det var en fil, og læse fra den på samme måde. Ved hjælp af fil abstraktionen kan vi hente data fra eksterne kilder, så som diske, netforbindelser og tastaturet.

Grundlaget for en sådan abstraktion er som regel en structure. For at bevare overblikket, for ikke at blande detaljerne ind i den abstraktion, som vi ønsker at skabe, indkapsles sådanne data ofte, således at al tilgang sker gennem funktionskald. Derved bliver det lettere at anvende den pågældende abstraktion, man skal blot udstede en "kommando": Læs, skriv, luk, flyt o.s.v.

Fil tilgang klares med funktionerne fopen(), fread(), fprintf() etc., som benytter datatypen FILE som parameter, for fopen() er det returværdien. FILE typen skal man ikke "dissekere", det er tilladt, men ikke fornuftigt at benytte de variable, som typen består af. FILE benyttes blot som et håndtag til den datastrøm, hvorpå man ønsker at udføre IO-operationer.

Eksempel 3-10. FILE typen

/* fileopen.c - demonstrerer fopen(). */
#include <stdio.h>

main()
{
        FILE *fp;
        fp = fopen("fileopen.c","r");
        if (!fp) {
                perror("Kan ikke aabne filen \"fileopen.c\"");
                exit(2);
        }
        printf("Har aabnet filen \"fileopen.c\" \n");
        return 0;
}
/* se Eksempel 2-20 for læsning fra en fil */

FILE er en abstrakt datatype. Hvis vi benytter vores program til at læse en "special-fil", for eksempel en driver-entry via /dev/ kataloget eller en fil i /proc/ kataloget, så har vi samme funktionalitet, som en C++ abstrakt datatype kan give os. For FILE typens vedkommende leveres funktionaliteten ikke af vores programkode, men af filsystemet i linux-kernen.

FILE "håndtaget" benyttes til at tilgå filer, og de indre dele af FILE (pointere, interface til kernen etc.) er ukendt for os, vi behøver ikke at vide noget om buffere og pointere, [1].

Det kan ikke understreges nok, at nøglen til succes er kendskab til funktions-interfacet og de andre teknikker til at indkapsle de data, der naturligt hører sammen.

Slutbemærkning:

[1]

Vi må selvfølgelig gerne vide, hvad der gemmer sig i en FILE, prøv selv at se efter i /usr/include/stdio.h og ikke mindst i /usr/include/libio.h som rummer selve struct-definitionen, bl.a.

  char* _IO_read_ptr;   /* Current read pointer */
  char* _IO_read_end;   /* End of get area. */
  char* _IO_read_base;  /* Start of putback+get area. */

Men selv om vi ved noget om _IO_FILE ville vi ikke drømme om at bruge denne viden i en end-user applikation!