Tiedosto yhteenkuuluvien tietojen joukko, joka on tavallisesti talletettu pysyväismuistiin muodostuu tietueista, jotka voivat olla keskenään samanlaisia tai vaihdella tyypiltään tiedostot ovat joko tekstitiedostoja tai binääritiedostoja tiedosto voi olla peräkkäistiedosto tai suorasaantitiedosto myös näppäimistösyötettä ja tulostusta näytölle voidaan käsitellä peräkkäistiedostona Tiedosto jatkossa käsitellään vain peräkkäistiedostoja, joiden tietuerakenne on (yleensä) kiinteä C-ohjelman käsittelemät tiedostot voidaan käsittää syöte- ja tulostusvirroiksi, jotka liitetään fyysisiin tiedostoihin ja/tai laitteisiin tietovirta (stream) on EOF-merkkiin päättyvä järjestetty jono tavuja oletustietovirrat stdin - syötevirta, oletuksena näppäimistö stdout - tulostus, oletuksena näyttö stderr - virheilmoitukset, oletuksena näyttö 1 T0004 Olli Hämäläinen www.evtek.fi 2 T0004 Olli Hämäläinen www.evtek.fi tiedostojen käsittely perustuu kirjastofunktioihin (stdio.h) tiedosto määritelllään C-ohjelmassa ottamalla käyttöön osoitin tiedoston kuvaajaan (tyyppiä FILE), esim. FILE *tiedosto1; osoitin liitetään todelliseen fyysiseen tiedostoon avaamalla tiedosto: tiedosto1=fopen(tiedoston_koko_nimi,avaustapa); esim. tiedosto1=fopen( d:\\temp\\ohje.txt, r ); 3 T0004 Olli Hämäläinen www.evtek.fi jokainen käsiteltävä tiedosto (oletusvirtoja lukuunottamatta) on avattava ennen käyttöä avaustapa kertoo, miten tiedostoa käytetään: r - avataan tekstitiedosto lukemista varten r+ - avataan tiedosto päivitystä varten w - luodaan uusi tai tyhjennetään olemassa oleva tekstitiedosto kirjoittamista varten w+ - luodaan uusi tai tyhjennetään olemassa oleva tiedosto päivitystä varten. a - avataan tekstitiedosto lisäystä varten a+ - avataan tai luodaan uusi tiedosto päivitettäväksi 4 T0004 Olli Hämäläinen www.evtek.fi jos tiedosto on binäärinen, lisätään avauskoodin perään b, siis: rb, wb, ab tiedosto-osoitin (tiedostopointteri) osoittaa kulloinkin käsiteltävään tiedoston kohtaan avauksen jälkeen tiedosto-osoitin osoittaa kirjoitustilassa ( w ) ja lukutilassa ( r ) tiedoston alkuun lisäystilassa ( a ) tiedoston loppuun kun tiedosto avataan kirjoitustilassa, sen aikaisempi sisältö katoaa 5 T0004 Olli Hämäläinen www.evtek.fi kun käsittely on päättynyt, tiedosto on suljettava funktiolla fclose, esim. tulos=fclose(tiedosto1); tiedoston sulkeminen aiheuttaa puskurien kirjoittamisen tiedostoon ja fyysisen tiedoston vapauttamisen tiedosto voidaan myös tuhota tai nimetä uudelleen C-ohjelmasta käsin funktioilla remove ja rename, esim. rename( a:\\vanha.txt, a:\\uusi.txt ); 6 T0004 Olli Hämäläinen www.evtek.fi 1
1. merkkien luku ja kirjoitus 2. rivien luku ja kirjoitus 3. muotoiltu luku ja kirjoitus 4. binäärinen luku ja kirjoitus Standardituloste- ja syöttötietovirtoja varten on joukko funktioita, joissa käsiteltävä tietovirta on sisäänrakennettuna itse funktiossa: putchar - tulostaa yhden merkin puts - tulostaa merkkijonon printf - tulostaa muotoillun merkkijonon getchar - lukee yhden merkin gets - lukee merkkijonon scanf - lukee muotoiltua tietoa 7 T0004 Olli Hämäläinen www.evtek.fi 8 T0004 Olli Hämäläinen www.evtek.fi kaikkia tietovirtoja (myös standarditietovirtoja) voidaan käsitellä standardikirjaston funktioilla, joissa käsiteltävä tietovirta annetaan parametrina tyypillisesti näiden funktioiden nimet alkavat pienellä f-kirjaimella tiedoston päättymistä voidaan luettaessa tutkia funktiolla feof (EOF = end of file) Merkkien luku ja kirjoitus fgetc - funktiolla (stdio.h) luetaan yksi merkki tietovirrasta: int fgetc(file *stream); int getc(file *stream); int getchar(); /* stdin-tietovirta */ fgetc palauttaa luetun merkin tai tiedoston loppuessa arvon EOF, jonka lukuarvo on -1 9 T0004 Olli Hämäläinen www.evtek.fi 10 T0004 Olli Hämäläinen www.evtek.fi Merkkien luku, esimerkki FILE *stream; int ch; /* HUOM! int, ei char */ stream = fopen("tied1.txt", "r"); do ch = fgetc(stream); fputc(ch,stdout); while (ch!= EOF); fclose(stream); 11 T0004 Olli Hämäläinen www.evtek.fi Merkkien luku, esimerkki 2 (SS 19.1) #include <stdlib.h> /* PŽŽOHJELMA***********************/ FILE *in, *out; char ch; if ((in=fopen("\\autoexec.bat", "r")) ==NULL) printf ("Sy tt tiedoston avaus ei onnistu "); exit (-1); /* lopetetaan ohjelman toiminta ja palautetaan DOS-tasolle virhekoodi -1*/ 12 T0004 Olli Hämäläinen www.evtek.fi 2
Merkkien luku, esimerkki 2 if ((out=fopen("\\autoexec.bak","w"))==null) printf("tulostiedoston avaus ei onnistu.\n"); exit(-1); ch = fgetc(in); while (!feof(in)) fputc(ch, out); ch = fgetc(in); fclose(in); fclose(out); 13 T0004 Olli Hämäläinen www.evtek.fi Merkkien luku ja kirjoitus fputc - funktiolla (stdio.h) kirjoitetaan yksi merkki tietovirtaan: int fputc(int c, FILE *stream); int putc(int c, FILE *stream); int putchar( int c );/* stdout-tietovirta */ fputc palauttaa nollan kun merkin kirjoitus onnistui ja muuten EOF. 14 T0004 Olli Hämäläinen www.evtek.fi Merkkien kirjoitus, esimerkki char msg[] = "Hello world"; int i = 0; while (msg[i]) fputc(msg[i], stdout); i++; Rivien luku ja kirjoitus fgets - funktio lukee yhden rivin tiedostosta rivi päättyy DOS-tiedostoissa CR ja LF merkkeihin, jotka muuntuvat luettaessa rivinvaihtomerkiksi '\n funktion fgets prototyyppi: char *fgets(char *s, int n, FILE *stream); n kertoo luettavien merkkien maksimilukumäärän, lukeminen päättyy joka tapauksessa rivinvaihtomerkkiin gets - funktio lukee yhden rivin standardisyötevirrasta ja muuttaa rivinvaihdon \0 :ksi char *gets(char *buffer); /*stdin-tietovirta*/ 15 T0004 Olli Hämäläinen www.evtek.fi 16 T0004 Olli Hämäläinen www.evtek.fi Rivien luku, esimerkki int main(int argc, char *argv[] ) FILE *stream; char mjono[200]; if ((stream = fopen(argv[1], "r"))!=null) while ( fgets( mjono, 200, stream ) ) printf( "%s", mjono ); Rivien luku ja kirjoitus fputs - funktio kirjoittaa merkkijonon tiedostoon: int fputs(const char *s, FILE *stream); merkkijonon päättävä nollatavu ei kirjoitu tiedostoon myöskään mitään rivinvaihtomerkkejä ei kirjoiteta tiedostoon onnistuessaan fputs palauttaa nollan, muuten jonkin nollasta poikkeavan arvon puts - funktio kirjoittaa stdout-tietovirtaan (standarditulostustietovirta) merkkijonon, jonka nollatavu korvataan rivinvaihtomerkillä '\n : int puts(const char *string); /* stdout */ 17 T0004 Olli Hämäläinen www.evtek.fi 18 T0004 Olli Hämäläinen www.evtek.fi 3
Rivien kirjoitus, esimerkki fputs("tiedon puussa asuu kyy:\n", stdout); fputs("joka sit\204 l\204hestyy\n", stdout); fputs("ikuisesti onneton\n", stdout); fputs("ep\204ilyksen uhri on.\n", stdout); fputs("autuas ken omin p\204in\n", stdout); fputs("el\204\204, kuolee lailla t\204in.\n", stdout); puts("\n\nlauri Viita"); Muotoiltu luku ja kirjoitus printf -jascanf - funktioista on olemassa vastaavat funktiot fprintf ja fscanf, joissa tietovirta annetaan parametrina: int fscanf( FILE *stream, const char *format[, address,...]); int fprintf( FILE *stream, const char *format[, argument,...]); fprintf- ja fscanf-funktioiden yhteydessä käytettävät muotoilumääreet ovat samat kuin printf- ja scanffunktioiden yhteydessä 19 T0004 Olli Hämäläinen www.evtek.fi 20 T0004 Olli Hämäläinen www.evtek.fi muun kuin tekstitiedon, esim. itse määritellyn tietuetyypin mukaisten tietuieiden tallettamiseen käytetään binääritiedostoja binääritiedostojen lukemiseen käytetään funktiota fread ja kirjoittamiseen fwrite yhdellä operaatiolla voidaan kerralla lukea tai kirjoittaa yksi tai useampia lohkoja lohkon koko voi olla yksi tai useampi tavu funktioiden prototyypit: size_t fread( void *puskuri, size_t lohkon_koko, size_t lohkojen_lkm, FILE *tietovirta); size_t fwrite( const void * puskuri, size_t lohkon_koko size_t lohkojen_lk FILE *tietovirta); 21 T0004 Olli Hämäläinen www.evtek.fi 22 T0004 Olli Hämäläinen www.evtek.fi puskuri osoittaa sen muuttujan johon luettu tieto sijoitetaan tai josta kirjoitettava tieto otetaan lohkon_koko ilmoittaa yhden luettavan tai kirjoitettavan lohkon koon tavuina lohkojen_lkm ilmoittaa kuinka monta lohkoa luetaan tai kirjoitetaan yhdellä kertaa fread palauttaa onnistuneesti luettujen lohkojen lukumäärän fwrite palauttaa onnistuneesti kirjoitettujen lohkojen lukumäärän Binäärinen kirjoitus, esimerkki #include <string.h> typedef struct char nimi[20]; int ika; double paino; HENKILO_TIETUE; 23 T0004 Olli Hämäläinen www.evtek.fi 24 T0004 Olli Hämäläinen www.evtek.fi 4
Binäärinen kirjoitus, esimerkki FILE *f1; double pii=3.141592; int luku= 374; char rivi[]="tämä on merkkijono\n"; HENKILO_TIETUE h1="antti",32,75.3; int lkm=strlen(rivi)+1; f1=fopen("bin.dat","wb"); fwrite(&h1,sizeof(h1),1,f1); fwrite(&pii,sizeof(pii),1,f1); fwrite(&lkm,sizeof(lkm),1,f1); fwrite(rivi,lkm,1,f1); fclose(f1); 25 T0004 Olli Hämäläinen www.evtek.fi Binäärinen luku, esimerkki typedef struct char nimi[20]; int ika; double paino; HENKILO_TIETUE; FILE *f1; double pii; int luku, lkm; char rivi[100]; HENKILO_TIETUE h1; 26 T0004 Olli Hämäläinen www.evtek.fi f1=fopen("bin.dat","rb"); fread(&h1,sizeof(h1),1,f1); fread(&pii,sizeof(pii),1,f1); fread(&luku,sizeof(luku),1,f1); fread(&lkm,sizeof(lkm),1,f1); fread(rivi,lkm,1,f1); fclose(f1); printf("henkilö nimi=%s\n",h1.nimi); printf("henkilö ikä=%i\n",h1.ika); printf("henkilö paino=%lf\n",h1.paino); printf("pii=%lf\n",pii); printf("luku=%i\n",luku); printf("rivi=%s\n",rivi); 27 T0004 Olli Hämäläinen www.evtek.fi 5