Programovací jazyk C podporuje mnoho standardních knihovních funkcí pro vstup a výstup souborů . Tyto funkce tvoří základ hlavičkového souboru standardní knihovny C. <stdio.h>
I/O funkčnost jazyka C je podle současných standardů implementována na nízké úrovni. Jazyk C abstrahuje všechny operace se soubory do operací s bajtovými proudy , které mohou být buď „vstupní proudy“ nebo „výstupní proudy“. Na rozdíl od některých raných programovacích jazyků jazyk C přímo nepodporuje náhodný přístup k datovým souborům; pro přečtení zapsané informace uprostřed souboru musí programátor vytvořit proud, který vypadá uprostřed souboru, a poté postupně číst bajty z proudu.
I/O model streamovaného souboru byl z velké části popularizován operačním systémem Unix napsaným v C. Velká část funkčnosti moderních operačních systémů zdědila streamy z Unixu a mnoho jazyků v rodině programovacích jazyků C zdědilo I/O rozhraní souboru C s malými rozdíly (např. PHP ). Standardní knihovna C++ odráží koncept streamování ve své syntaxi (viz iostream ).
Soubor je otevřen pomocí funkce fopen, která vrací informace o I/O streamu připojeném k zadanému souboru nebo jinému zařízení, ze kterého se čte (nebo do něj zapisuje). Při selhání funkce vrátí ukazatel null .
Podobná freopenfunkce knihovny C provede podobnou operaci po prvním uzavření jakéhokoli otevřeného proudu spojeného s jejími parametry.
Vyhlašují se jako
FILE * fopen ( const char * cesta , const char * režim ); FILE * freopen ( const char * cesta , const char * režim , FILE * fp );Funkce fopenje v podstatě „obalem“ pro systémové volání vyšší úrovně open operačního systému Unix . Podobně fcloseje to obal kolem unixového systémového volání closea FILEsamotná struktura jazyka C často odkazuje na odpovídající unixový souborový deskriptor . V prostředí POSIX lze funkci fdopenpoužít k inicializaci struktury pomocí FILEdeskriptoru souboru. Nicméně deskriptory souborů jako čistě unixový koncept nejsou ve standardu jazyka C zastoupeny.
Parametr mode(režim) pro fopena freopenmusí být řetězec a začínat jednou z následujících sekvencí:
režimu | popis | začíná s.. | ||
---|---|---|---|---|
r | rb | otevře se ke čtení | Start | |
w | wb | otevře se pro zápis (vytvoří soubor, pokud neexistuje). Smaže obsah a přepíše soubor. | Start | |
A | ab | otevře se pro připojení (vytvoří soubor, pokud neexistuje) | konec | |
r+ | rb+ | r+b | otevře se pro čtení a psaní | Start |
w+ | wb+ | w+b | otevře se pro čtení a psaní. Smaže obsah a přepíše soubor. | Start |
a+ | ab+ | a+b | otevře se pro čtení a zápis (vytvoří soubor, pokud neexistuje) | konec |
Hodnota „ b “ je vyhrazena pro binární režim C. Standard jazyka C definuje dva druhy souborů – textové a binární – ačkoli operační systém nevyžaduje, abyste mezi nimi rozlišovali (některé kompilátory, jako je LCC , však specifikují 'b' při práci s binárním souborem je zásadně důležité!). Textový soubor je soubor obsahující text rozdělený do řádků nějakým oddělovacím znakem nebo sekvencí na konci řádku (v Unixu , jeden řádek \n, v systému Microsoft Windows , po řádku následuje znak konce řádku ) \r\n. Při čtení bajtů z textového souboru jsou znaky konce řádku obvykle spojeny (nahrazeny) s novými řádky, aby se zjednodušilo zpracování. Při psaní textového souboru je jeden znak nového řádku před zápisem spojen (nahrazen) se sekvencí znaků na konci řádku specifickou pro operační systém. Binární soubor je soubor, ze kterého se čtou a vydávají bajty v „raw“ podobě bez jakéhokoli spojování (substituce).
Když je soubor otevřen v režimu aktualizace (' + ' jako druhý nebo třetí znak argumentu označení režimu), lze vstup i výstup provádět ve stejném vláknu. Zápis však nemůže následovat po čtení bez zprostředkujícího volání fflushnebo funkce pozice souboru ( fseek, fsetposnebo rewind) a čtení nemůže následovat po zápisu bez zprostředkujícího volání funkce pozice souboru. [jeden]
Režimy zápisu a připojení se pokusí vytvořit soubor s daným názvem, pokud takový soubor již neexistuje. Jak je uvedeno výše, pokud tato operace selže, fopenvrátí NULL.
Funkce fclosemá jeden argument: ukazatel na strukturu proudu , která FILEse má zavřít.
int fclose ( FILE * fp );Funkce vrací nulu při úspěchu a EOF při neúspěchu. Když se program normálně ukončí, funkce se zavolá automaticky pro každý otevřený soubor.
Funkce fgetcse používá ke čtení znaku ze streamu.
int fgetc ( SOUBOR * fp );Pokud je úspěšný fgetc, vrátí další bajt nebo znak ze streamu (v závislosti na tom, zda je soubor „binární“ nebo „textový“, jak je uvedeno výše). Jinak fgetcse vrací EOF. (Konkrétní typ chyby lze identifikovat voláním ferrornebo feofpomocí ukazatele na soubor.)
Standardní makro getc je také definováno v <stdio.h>, funguje úspěšně jako fgetc, s výjimkou jedné věci: protože jde o makro, může zpracovat své argumenty více než jednou.
Standardní funkce getcharje také definována v <stdio.h>, nebere žádné argumenty a je ekvivalentní . getc(stdin)
"Pasti" EOFČastou chybou je použití fgetcnebo přiřazení výsledku k typové proměnné getcpřed jejím porovnáním s . Následující fragment kódu ukazuje tuto chybu a vedle něj je zobrazena správná verze: getcharchar EOF
Chyba | Správně |
---|---|
char c ; while (( c = getchar ()) != EOF ) { putchar ( c ); } | int c ; while (( c = getchar ()) != EOF ) { putchar ( c ); } |
Uvažujme systém, kde typ chardlouhý 8 bitů (konkrétně architektura x86 ) představuje 256 různých hodnot. getcharmůže vrátit kterýkoli z 256 možných znaků a může se také vrátit EOFk označení konce souboru, jehož hodnota se nemůže shodovat s žádnou z hodnot char.
Když je výsledek getcharpřiřazen k proměnné typu char, která může představovat pouze 256 různých hodnot, dochází k nucené ztrátě informací – když je 257 hodnot komprimováno na 256 „míst“ , dojde ke kolizi . Hodnota se EOFpo převodu na charnerozezná od ostatních 256 znaků. Pokud je tento znak nalezen v souboru, výše uvedený kód jej může považovat za konec souboru, nebo v horším případě, pokud je typ char bez znaménka, pak vzhledem k tomu, že EOF - je záporná hodnota, nemůže se nikdy rovnat žádnému nepodepsanému char. výše uvedený příklad neskončí na značce konce souboru, ale bude běžet navždy a znovu vytiskne znak vzniklý převodem EOFna char.
V systémech, kde inta charjsou stejné velikosti[ co? ] , ani ta "správná" verze nebude fungovat správně kvůli podobnosti EOFa jinému znaku. Správný způsob, jak tuto situaci vyřešit, je zkontrolovat feofa ferrorpoté, co se getcharvrátí EOF. Pokud feofzjistí, že ještě nebylo dosaženo konce souboru, ale ferror„oznámí“, že nejsou žádné chyby, pak lze EOFvrácený getcharpovažovat za aktuální znak. Takové zvláštní kontroly se provádějí jen zřídka, protože většina programátorů předpokládá, že jejich kód nikdy nepoběží na tak "velkých char" systémech. Dalším způsobem je použití kontroly během kompilace, která UINT_MAX > UCHAR_MAXalespoň zabrání kompilaci na takových systémech.
Funkce fgetsse používá ke čtení řetězce z proudu. Čtení pokračuje, dokud není dosaženo buď konce řádku ( hex :0D0A, ekvivalentní ve výpisech \n ) nebo délky čteného řádku. Předpokládejme, že máme soubor some_file.txt s textem
palindromy A v Jeniseji - modrá. A lama je malá. A liška, ten je chytrý - krysa mu nosila sýr. (I. Babitsky) #include <stdio.h> #include <řetězec.h> int main ( int argc , char * argv []) /* argc ukládá počet parametrů a argv[] ukazuje na tyto parametry. Pokud například spustíme spustitelný soubor "fgets_example param1 param2", pak se argc bude rovnat 3 a argv[] = { "fgets_example" , "param1" , "param2" } */ { SOUBOR * soubor ; char * fname = "nejaky_soubor.txt" ; char result_string [ 20 ]; //Řetězec 20 znaků soubor = fopen ( fname , "r" ); if ( soubor == NULL ) { printf ( "nelze otevřít soubor '%s'" , fname ); návrat 0 ; } int i = 0 ; char * real_tail ; while ( fgets ( result_string , sizeof ( result_string ), file )) { real_tail = "" ; printf ( "Řetězec %d:Délka řetězce - %d:" , i ++ , strlen ( řetězec_výsledku )); if ( result_string [ řetězec ( result_string ) -1 ] == '\n' ) // kontrola, zda je poslední prvek v řetězci koncový znak { real_tail = " \\ n" ; řetězec_výsledku [ řetězec ( řetězec_výsledku ) -1 ] = '\0' ; }; // tato část kódu byla přidána pouze pro zobrazení znaku konce řádku v konzole bez nového řádku printf ( "%s%s \n " , result_string , real_tail ); } fclose ( soubor ); návrat 0 ; }v důsledku provedení dostaneme
Řádek 0: Délka řádku - 11: palindromy\n Linka 1: Délka linky - 19: A v Yenisei - si Řádek 2:Délka řádku - 6:neva.\n Řádek 3: Délka čáry je 17: A lama je malá.\n Řádek 4: Délka řádku - 19: Liška, je chytrý Řádek 5: Délka řádku - 19: - krysí sýr k tomu Řádek 6: Délka řádku - 19: nošené. (I. Babitský Řádek 7: Délka řádku – 2:th)Funkce strlen určuje délku řetězce počtem znaků až do '\0', například:
printf ( "%d" , strlen ( "123 \0 123" )); //výstup 4V programovacím jazyce C funkce fread, fwriteresp. implementují operace vstupu a výstupu souboru . a prohlásil v . freadfwrite <stdio.h>
fwrite je definován jako
int fwrite ( const char * pole , size_t size , size_t count , FILE * stream );Funkce fwritezapíše blok dat do streamu. Tím se zapíše pole prvků arrayna aktuální pozici ve streamu. Pro každý prvek bude zapsán sizebajt . Indikátor pozice toku se změní na počet úspěšně zapsaných bajtů. Vrácená hodnota bude rovna count, pokud byl zápis úspěšně dokončen. V případě chyby bude vrácená hodnota menší než count.
Následující program otevře ukázkový soubor .txt , zapíše do něj řetězec znaků a poté jej zavře.
#include <stdio.h> #include <řetězec.h> #include <stdlib.h> int main ( void ) { SOUBOR * fp ; size_t count ; char const * str = "ahoj \n " ; fp = fopen ( "example.txt" , "wb" ); if ( fp == NULL ) { perror ( "chyba při otevírání example.txt" ); return EXIT_FAILURE ; } count = fwrite ( str , sizeof ( char ), strlen ( str ), fp ); printf ( "%lu zapsaných bajtů. fclose(fp) %s. \n " , ( dlouhé bez znaménka ) počet , fclose ( fp ) == 0 ? "úspěch" : "chyba" ); fclose ( fp ); návrat 0 ; }Funkce fputcslouží k zápisu znaku do streamu.
int fputc ( int c , SOUBOR * fp );Tichá cvolba je převedena na unsigned charpřed výstupem. V případě úspěchu fputcvrátí zapsaný znak. Pokud dojde k chybě, fputcvrátí EOF.
Standardní makro putcje také definováno v <stdio.h>, funguje obecně stejným způsobem fputc, kromě toho, že jako makro může zpracovat své argumenty více než jednou.
Standardní funkce putchar, také definovaná v <stdio.h>, přebírá pouze první argument a je ekvivalentní , kde je zmíněný argument. putc(c, stdout)c
Následující program C otevře binární soubor s názvem myfile , přečte z něj pět bajtů a pak soubor zavře.
#include <stdio.h> #include <stdlib.h> int main ( void ) { charbuffer [ 5 ] = { 0 } ; /* inicializovat s nulami */ int i , rc ; FILE * fp = fopen ( "myfile" , "rb" ); if ( fp == NULL ) { perror ( "Chyba při otevírání \" myfile \" " ); return EXIT_FAILURE ; } for ( i = 0 ; ( rc = getc ( fp )) != EOF && i < 5 ; buffer [ i ++ ] = rc ); fclose ( fp ); if ( i == 5 ) { vloží ( "Načtené bajty..." ); printf ( "%x %x %x %x %x \n " , vyrovnávací paměť [ 0 ], vyrovnávací paměť [ 1 ], vyrovnávací paměť [ 2 ], vyrovnávací paměť [ 3 ], vyrovnávací paměť [ 4 ]); } jinak fputs ( "Chyba při čtení souboru. \n " , stderr ); return EXIT_SUCCESS ; }