Fájlkezelés

Czirkos Zoltán · 2018.08.29.

Segédlet a nagy házihoz: röviden a fájlkezelésről azoknak, akik nem akarják megvárni az erről szóló előadást.

C-ben nagyon egyszerű a szövegfájlok kezelése. A szabványos bemenetet és kimenetet kezelő scanf() és printf() függvényeknek is van olyan változata, amelyik fájlból és fájlba dolgozik. Ezek az fscanf() és az fprintf(). Ezek első paraméterként megkapják a fájlt, amellyel dolgozniuk kell, amúgy pedig a használatuk teljesen megegyezik az előbb említett függvényekkel.

Fájlt megnyitni, létrehozni az fopen() nevű függvénnyel lehet. Ennek visszatérési értéke egy ún. file handle, amellyel a megnyitott fájlra hivatkozunk (mert egyszerre több fájllal is dolgozhatunk). A használat nagyon röviden az alábbi programban látszik. Ez a klasszikus „helló, világ” program, azzal a különbséggel, hogy nem a képernyőre, hanem a hello_world.txt fájlba írja az üzenetet.

#include <stdio.h>

int main(void) {
    /* Az fp változóval hivatkozunk majd a nyitott fájlra. */
    FILE* fp;
    
    /* Létrehozzuk a fájlt, w = write = írni fogunk bele. */
    fp = fopen("hello_world.txt", "w");
    
    /* Beleírjuk a "Helló, világ!" szöveget. */
    fprintf(fp, "Helló, világ!\n");
    
    /* Végeztünk, bezárjuk a fájlt. */
    fclose(fp);

    return 0;
}

A megnyitás sikerességét egyébként ellenőrizni kell, mert előfordulhat, hogy nem sikerül valamilyen okból létrehozni a fájlt (pl. rossz helyen próbáljuk, nincs oda írási jogunk, és így tovább). A hibát úgy látjuk, hogy az fopen() függvény NULL értéket ad vissza. Ilyenkor a perror()-ral szokás hibaüzenetet kiírni, mert az egyből kiírja a sikertelenség okát is. És természetesen ilyenkor a fájlműveleteket (írás, zárás) nem végezhetjük el, mert nincs értelme.

#include <stdio.h>

int main(void) {
    FILE* fp;
    fp = fopen("szamok.txt", "w");  /* file-open, w = write */
    if (fp != NULL) {
        for (int i = 1; i <= 10; ++i)
            fprintf(fp, "%d\n", i); /* file-printf */
        fclose(fp);                 /* file-close */
    }
    else {
        perror("Nem sikerült megnyitni a fájlt");
    }

    return 0;
}

Ennyi. Az olvasás ugyanez; w helyett r (mert read), és fprintf() helyett fscanf(). Beolvasás közben a fájlból sorban kapjuk az adatokat, az elejétől végéig; mintha a fájl tartalmát a felhasználó folyamatosan gépelné be.

Fájl beolvasásánál gyakori az, hogy nem közvetlenül a fájlból fscanf()-elünk, hanem komplett sorokat olvasunk be, és utána a beolvasott sorokból, sztringekből vesszük ki az adatokat. Ez azért előnyös, mert így könnyebb kezelni a hibás fájlokat: tudjuk, hogy mekkora egységeket olvasunk be a fájlból, nem a sor közepén akad el hiba esetén a beolvasás. A beolvasott sor tartalma alapján pedig bonyolultabb esetszétválasztásokat is meg tudunk csinálni. A módszer ehhez hasonló:

FILE* fp;
fp = fopen("fajl.txt", "r");  /* r = read */

/* ... */

char sor[101];
fgets(sor, 101, fp);
/* beolvasott sor kezelése... */
if (baj_van) {
    printf("Hibás sor: %s", sor);
}

/* ... */

A beolvasott soron akár sscanf(), strtok() vagy más sztringkezelő függvények is használhatók.