Učíme se C (20. díl) - Práce se soubory II. - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



C/C++

Učíme se C (20. díl) - Práce se soubory II.

23. února 2001, 00.00 | Dnes si uvedeme funkce pro čtení a zápis do souboru (především pak blokové
vstupně-výstupní funkce) a podporu nesekvenčního přístupu k souboru.

Funkce pro zápis do souboru

Pro zápis do souboru nám poslouží funkce putc(), fprintf(), a fputs(), jejichž deklarace jsou zde:

int putc(int c, FILE *file);
int fprintf(FILE *file, char *formát, ...);
int fputs (char *string, FILE *file);

Asi nemá cenu dlouho se u těchto funkcí zdržovat, neboť jejich chování je podobné jim příbuzným funkcím putchar, printf a puts, které slouží pro zápis na standardní výstup, a které jsme již probrali v desátém dílu tohoto seriálu. Je nutné pouze říct, že po provedení některé z těchto funkcí se file-pointer posune v souboru za poslední zapsaný byte. To ostatně platí i pro všechny další funkce zapisující do souboru. Teď se ale raději podíváme na funkci pro blokový zápis.

Funkce fwrite()

int fwrite(void *ptr, int size, int n, FILE *file);

Funkce fwrite() zapíše do proudu file n položek přečtených z paměti označené ukazatelem ptr. Velikost jedné položky v bytech udává parametr size, takže celkový počet zapisovaných bytů je roven size*n. Funkce fwrite() vrací počet úspěšně zapsaných položek, nikoli bytů!

Příklad použití funkce fwrite se nachází níže, v části věnované funkci fread.

Funkce pro čtení ze souboru

Obdobně jako při zápisu do souboru, i pro čtení jsou definovány podobné funkce, jaké jsme používali při čtení ze standardního vstupu:

int   getc(FILE *file);
int   fscanf(FILE *file, char *formát, ...);
char *fgets(char *string, int n, FILE *file);

Zajímavá je především funkce fgets, která oproti příbuzné funkci gets umožňuje definovat maximální počet přečtených znaků. Protože standardní vstup i výstup jsou také datové proudy (jsou automaticky inicializované při spuštění programu) můžeme pro čtení ze standardního vstupu použít, namísto funkce gets, bezpečnou fgets:

char str[50];

fgets(str, 49, stdin);

I funkce čtoucí ze souboru posouvají file-pointer, a to za poslední přečtený znak souboru.

Funkce fread()

Pro blokové čtení ze souboru nám poslouží funkce fread():

int fread(void *ptr, int size, int n, FILE *file);

Z datového proudu file přečte n položek o velikosti size bytů a uloží je do paměti označené ukazatelem ptr. Návratovou hodnotou je počet skutečně přečtených položek.

V následujícím příkladu uložíme do souboru data.bin pole struktur ar1 a v jiné části programu tento soubor načteme do pole ar2. Pro jednoduchost nebudeme ošetřovat chybové stavy (soubor se nepodařilo otevřít, nepodařilo se zapsat/přečíst potřebný počet položek):

#define POCET 10

typedef struct { int x;
                 double y;
               } MY_STRUCT;

const char my_file[]="data.bin";
MY_STRUCT  ar1[POCET], ar2[POCET];
FILE      *f;

...


f=fopen(my_file, "wb");
fwrite(ar1,sizeof(MY_STRUCT), POCET, f);
fclose(f);

...

f=fopen(my_file, "rb");
fread(ar2,sizeof(MY_STRUCT), POCET, f);
fclose(f);

...


Nesekvenční přístup

Na souborové datové proudy lze použít tzv. nesekvenční (náhodný) přístup, což znamená, že nemusíme číst jeden byte za druhým tak, jak jsou v souboru uloženy, ale můžeme „skákat“ (přesunovat file-pointer) na libovolnou pozici v souboru. K tomuto účelu slouží funkce fseek().

int fseek (FILE *file, long offset, int mode);

Funkce přesune file-pointer na pozici vzdálenou offset bytů od pozice mode, přičemž za parametr mode je možné zvolit jednu z následujících konstant:

SEEK_SET Začátek souboru
SEEK_CUR Aktuální pozice v souboru
SEEK_END Konec souboru

Př:

zápis file-pointer se přesune na...
fseek(f, 0, SEEK_SET); 
začátek souboru
fseek(f, 0, SEEK_END); 
konec souboru
fseek(f, -10, SEEK_CUR); 
pozici o deset bytů zpět od aktualní pozice
fseek(f, 10, SEEK_SET); 
jedenactý byte souboru

Je-li soubor, se kterým pracujeme, otevřen v módu pro čtení i zápis, musíme mezi každou operací čtení a operací zápisu volat funkci fseek(). Tato nepříjemnost je nutná kvůli synchronizaci file-pointerů, které jinak nemusí být správně nastaveny. Funkci fseek() ale můžeme volat i s nulovým posunem. Tento postup si ukážeme na příkladu, ve kterém ve streamu f převedeme všechna malá písmena na velká.

FILE *f;
int   c;

f = fopen("text.txt", "r+b");
if (f==NULL) { puts("Soubor text.txt se nepodařilo otevřít.");
               exit(1);
             }

while ((c=getc(f))!=EOF)   //načtení c a test konce souboru
if (c>='a' && c<='z')      //test, zda je c malé písmeno
 { fseek(f, -1, SEEK_CUR);
   putc(c + 'A'-'a', f);   //převod na velké písmeno a zápis
   fseek(f, 0, SEEK_CUR);  //posun o 0 bytů kvůli synchronizaci
 }

fclose(f);

Pro zjednodušení bychom v uvedeném příkladu ještě mohli použít makra islower() (pro detekci znaku malého písmena) a toupper() (pro převod na velké písmeno).

Chceme-li zjistit, jaká je aktuální pozice file-pointeru v souboru, můžeme použít funkci ftell(), která tuto pozici vrací jako svou návratovou hodnotu.

long ftell (FILE *file);

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » C/C++  

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: