© Harry Broeders.
Deze pagina is bestemd voor studenten van de THRijswijk groepen EPm en EPv die de module SOPX1 volgen.
De programmeertaal C onderscheidt 2 soorten files:
getc
of fscanf
. Schrijven in tekstfiles gaat met de functie:
putc
of fprintf
.
int
variabele). De inhoud van de file in hexadecimale notatie
is dan 00 00 00 7B. Binairefiles worden behandeld op p237 t/m p259 van het
boek. Binairefiles worden ook wel random access files genoemd. Als je ervoor
zorgt dat de file ingedeeld is in blokken van gelijke grootte dan kun je
snel het blok met een specifieke index zoeken zonder dat je alle voorgaande
blokken moet inlezen. Lezen uit binairefiles gaat met de functie:
fread
. Schrijven in binairefiles gaat met de functie
fwrite
. Zoeken gaat met de functie fseek
.
Je kunt de volgende bewerkingen op tekstfiles uitvoeren:
Om een tekstfile te kunnen lezen of beschrijven moet de file eerst geopend
worden. Je kunt een file openen met de functie fopen
. Deze functie
is in de include file stdio.h
als volgt gedeclareerd:
FILE *fopen(const char *filename, const char *mode);
Het returntype is een FILE*
. Dit wordt een filepointer
genoemd. Deze filepointer kun je, als de file eenmaal geopend is, gebruiken
om uit de file te lezen of om in de file te schrijven. Deze pointer wijst
niet rechtstreeks naar de file. Dat kan namelijk niet want de file bevindt
zich niet in het werkgeheugen (RAM) van de PC maar in het achtergrond geheugen
(bijvoorbeeld op de harddisk). De filepointer wijst naar een zogenaamde file
control structure waarin informatie wordt bijgehouden waarmee het operating
systeem de echte file kan benaderen. Een filepointer zou dus eigenlijk file
control structure pointer genoemd moeten worden.
Via de parameter filename
kun je de naam van de file die je
wilt openen meegeven. Als je alleen een naam opgeeft wordt de file in het
"huidige" directory opgezocht. Je kunt ook de relatieve of absolute padnaam
opgeven. Let er daarbij op dat de backslash in C strings gebruikt wordt als
escape karakter. Één backslash moet dus worden ingetyped als
twee backslashes.
Bijvoorbeeld "C:\\Mijn documenten\\testbestand.txt"
.
Via de parameter mode
kun je opgeven hoe je de file wilt openen:
"r" |
Open om te lezen (read). Als de file niet bestaat is dat een fout. |
"w" |
Open om te schrijven (write). Als de file niet bestaat dan wordt deze aangemaakt. Als de file al bestaat wordt deze file overschreven. |
"a" |
Open om te schrijven aan het einde van de file (append). Als de file niet bestaat dan wordt deze aangemaakt. |
"r+" |
Open om te lezen en te schrijven. Als de file niet bestaat is dat een fout. |
"w+" |
Open om te lezen en te schrijven. Als de file niet bestaat dan wordt deze aangemaakt. Als de file al bestaat wordt deze file overschreven. |
"a+" |
Open om te lezen en te schrijven aan het einde van de file. Als de file niet bestaat dan wordt deze aangemaakt. |
Als alles goed gaat geeft fopen
een geldige FILE*
terug. Als er een fout optreedt (bijvoorbeeld omdat de file die je wil lezen
niet bestaat of omdat je een file wil schrijven naar een CD-ROM) geeft
fopen
de waarde NULL
terug. NULL
is
gedefineerd in stdio.h
.
Nadat de filepointer gebruikt is om uit de file te lezen of om in de file
te schrijven moet de file weer worden gesloten. Het is belangrijk om een
file zo snel mogelijk te sluiten omdat andere applicaties de file niet kunnen
openen zolang de file al geopend is. Als een programma eindigt zal het operating
systeem alle open files zelf sluiten. Het is echter netter als het programma
dit zelf doet met de functie fclose
. Deze functie is in de include
file stdio.h
als volgt gedeclareerd:
int fclose(FILE *stream);
Deze functie geeft de integer waarde EOF
terug als er een fout
optreed. Als parameter moet een FILE*
worden meegegeven die
je hebt teruggekregen van de functie fopen
.
Er zijn verschillende functies beschikbaar om uit een tekstfile te lezen.
getc
.
De eenvoudigste functie is getc
. Deze functie leest 1 karakter
uit de file en is in de include file stdio.h
als volgt gedeclareerd:
int getc(FILE *stream);
Als parameter moet een FILE*
worden meegegeven die je hebt
teruggekregen van de functie fopen
.
Deze functie geeft geen char
terug maar een
int
! Als het lukt om een karakter uit de file te lezen geeft
getc
(de ASCII waarde van) het ingelezen karakter terug. De
functie geeft de speciale integer waarde EOF
terug als er iets
fout gaat. EOF
is gedefinieerd in stdio.h
. Doordat
de functie een int
teruggeeft kan elke char waarde worden
teruggegeven plus de speciale errorcode EOF
.
Let goed op:
EOF
is geen karakter! Aan het einde van de file staat
geen speciaal karakter. Het operating systeem houd voor elke file
het aantal bytes in de file bij (de filelengte). Op deze manier kan een file
alle mogelijke bytewaarden bevatten. Op het moment dat een programma meer
karakters probeert te lezen als de filelengte geeft de functie
getc
de integer waarde EOF
terug.
EOF
kun je niet opslaan in een char
!
EOF
is meestal gedefinieerd als de integer -1
.
Deze waarde is hexadecimaal FF FF FF FF. Als je deze waarde in een
char
variabele stopt passen daar alleen de laatste 8 bits in.
Deze char
variabele wordt dan gelijk aan hexadecimaal FF. Het
hangt van de karakterset af welk karakter dit is. Op de PC is dit voor de
meeste lettertypes het karakter ÿ en dat is dus heel wat anders dan
de integer waarde EOF
.
getc
altijd op in een
int
! Een veelgemaakte fout is het opslaan van de returnwaarde
van getc
in een char
. Dat is niet goed omdat
deze waarde dan niet meer correct met EOF
vergeleken kan worden.
In het boek wordt deze fout op p180, p184 en p194 gemaakt. Zie onderstaand
voorbeeld.
Het volgende programma leest de file
testfile.txt
karakter voor karakter
in en schrijft deze karakters naar het beeldscherm.
#include <stdio.h>
int main() {
int c;
FILE *fp;
fp=fopen("testfile.txt", "r");
if (fp==NULL) {
printf("Kan file testfile.txt niet openen!");
}
else {
c=getc(fp);
while (c!=EOF) {
putchar(c);
c=getc(fp);
}
fclose(fp);
}
getchar();
return 0;
}
Als in de file testfile.txt
de volgende regel staat: "In het
Nederlands is een ij geen ÿ en ook geen y." Dan wordt deze regel als
volgt afgedrukt op het scherm:
De ÿ wordt niet afgedrukt omdat dit karakter in het, in de DOS box gebruikte, lettertype niet bestaat.
Als in het bovenstaande programma de regel:
int c;
vervangen wordt door:
char c;
dan geeft dit programma de volgende uitvoer:
Je ziet dat het programma nu stopt voordat het eind van de file bereikt is!
fscanf
.
In plaats van karakter voor karakter in te lezen kun je ook zogenaamde
geformateerde invoer doen. Dit houdt in dat de ingelezen karakters worden
omgezet naar het gewenste type. Je bent al bekend met geformateerde invoer
vanaf het toetsenbord met de functie scanf
. Geformateerde invoer
vanuit een file gaat op vergelijkbare wijze met de functie
fscanf
. Deze functie is in de include file stdio.h
als volgt gedeclareerd:
int fscanf(FILE *stream, const char *format[, address, ...]);
Als eerste parameter moet een FILE*
worden meegegeven die je
hebt teruggekregen van de functie fopen
. De overige parameters
zijn hetzelfde als bij de al bekende functie scanf
.
De functie geeft de integer waarde EOF
terug als er iets fout
gaat bij het inlezen. Anders geeft de functie het aantal variabelen terug
dat succesvol is geconverteerd en ingelezen. Zie onderstaande
voorbeeldprogramma:
#include <stdio.h>
int main() {
int i;
int ret;
FILE *fp;
fp=fopen("getallenfile.txt", "r");
if (fp==NULL) {
printf("Kan file getallenfile.txt niet openen!");
}
else {
do {
ret=fscanf(fp, "%d", &i);
switch (ret) {
case 0:
printf("Dat was geen getal!\n");
printf("Maar het karakter %c.\n", getc(fp));
break;
case 1:
printf("Dat was het getal %d.\n", i);
break;
case EOF:
printf("Dat was het einde.\n");
break;
default:
printf("Dat kan niet!\n");
break;
}
}
while (ret!=EOF);
fclose(fp);
}
getchar();
return 0;
}
Als in de file
getallenfile.txt
de volgende
regel staat: "1234 a56789" Dan wordt het volgende afgedrukt op het scherm:
Met behulp van scanf
en
fscanf
kun je ook woorden inlezen vanaf het toetsenbord of vanuit
een file. Deze woorden worden dan opgeslagen in een char
array.
Hierbij moet je goed oppassen voor buffer overrun. Dit probleem treedt op
als de invoer meer karakters bevat als de char
array kan bevatten.
Voorbeeld:
#include <stdio.h>
#include <string.h>
int main() {
char password[]="Geheim", buffer[10];
printf("Geef password: ");
scanf("%s", buffer);
if (strncmp(password, buffer, 7)==0) {
printf("Toegang tot geheime informatie.");
}
else {
printf("Onjuist password!");
}
getchar();
getchar();
return 0;
}
De functie
strncmp
hebben we nog niet behandeld. Deze functie uit string.h
vergelijkt
een aantal karakters van twee als parameters meegegeven strings. Het aantal
karakters dat vergeleken moet worden wordt als derde parameter meegegeven.
Deze functie geeft 0
terug als de strings gelijk zijn (waarbij
alleen gekeken wordt naar het aantal meegegeven karakters).
Je zou denken dat je alleen toegang tot de geheime informatie krijgt als
je het password kent1. Als dit programma
met Borland C++ 5.02 wordt gecompileerd blijkt dat de variabele
password
12 bytes na de variabele buffer
in het
geheugen wordt geplaatst. Als we meer dan 10 karakters invoeren worden deze
karakters allemaal in het geheugen weggeschreven (buffer overrun). Op deze
manier kan ook de variabele password
overschreven worden.
Buffer overrun kun je eenvoudig voorkomen door in de functies
scanf
en fscanf
altijd een maximaal in te lezen
karakters bij het format %s
te gebruiken. In het bovenstaande
programma moet de regel:
scanf("%s", buffer);
worden vervangen door:
scanf("%9s", buffer);
De functie zal nu hooguit 9 karakters inlezen (en de tiende plaats in de buffer vullen met het nul karakter).
1 Ik ben er wel vanuit gegaan dat de gebruiker
alleen uitvoerrechten heeft voor het programma en geen leesrechten! Anders
zou de gebruiker namelijk eenvoudig het geheime password kunnen opsporen
door de bufferoverrun.exe
file in notepad te laden. Als de gebruiker
ook leesrechten heeft op de executable moeten we het password "encrypted"
in de exe file opslaan.
fgets
en andere functies.
Er zijn nog meer functies gedeclareerd in stdio.h
om informatie
uit tekstfiles te kunnen lezen, bijvoorbeeld
fgets
.
Deze functies worden hier niet verder behandeld maar kunnen via de link of
in de helpfile van Borland C++ 5.02 worden opgezocht.
Er zijn verschillende functies beschikbaar om in een tekstfile te schrijven.
putc
.
De eenvoudigste functie is putc
. Deze functie schrijft 1 karakter
in de file en is in de include file stdio.h
als volgt gedeclareerd:
int putc(int c, FILE *stream);
Als eerste parameter moet het karakter worden meegegeven dat in de file moet
worden weggeschreven. Als tweede parameter moet een FILE*
worden
meegegeven die je hebt teruggekregen van de functie fopen
.
Als het lukt om een karakter in de file te schrijven geeft putc
het weggeschreven karakter terug. De functie geeft de speciale integer waarde
EOF
terug als er iets fout gaat.
Het volgende programma kopieert de file
infile.txt
naar de file
outfile.txt
waarbij alle kleine letters
worden omgezet naar hoofdletters.
#include <stdio.h>
#include <ctype.h>
int main() {
int c;
FILE *infile, *outfile;
infile=fopen("infile.txt", "r");
if (infile==NULL) {
printf("Kan file infile.txt niet openen!");
}
else {
outfile=fopen("outfile.txt", "w");
if (outfile==NULL) {
printf("Kan file outfile.txt niet openen!");
}
else {
c=getc(infile);
while (c!=EOF) {
c=putc(toupper(c), outfile);
if (c==EOF) {
printf("Fout tijdens schrijven in outfile.txt!");
}
else {
c=getc(infile);
}
}
fclose(outfile);
}
fclose(infile);
}
getchar();
return 0;
}
fprintf
.
In plaats van karakter voor karakter weg te schrijven kun je ook zogenaamde
geformateerde uitvoer doen. Dit houdt in dat variabelen van verschillende
typen in een opgegeven formaat worden omgezet naar karakters die naar de
file worden geschreven. Je bent al bekend met geformateerde uitvoer naar
het beeldscherm met de functie printf
. Geformateerde uitvoer
naar een file gaat op vergelijkbare wijze met de functie
fprintf
. Deze functie is in de include file stdio.h
als volgt gedeclareerd:
int fprintf(FILE *stream, const char *format[, argument, ...]);
Als eerste parameter moet een FILE*
worden meegegeven die je
hebt teruggekregen van de functie fopen
. De overige parameters
zijn hetzelfde als bij de al bekende functie printf
.
De functie geeft de integer waarde EOF
terug als er iets fout
gaat bij het wegschrijven. Anders geeft de functie het aantal karakters terug
dat succesvol is weggeschreven.
In het volgende voorbeeld wordt aan de integer
variabele i
de waarde 123
toegekend en daarna wordt
deze variabele weggeschreven in een tekstfile. (Dit is natuurlijk volkomen
zinloos maar maakt wel duidelijk hoe het werkt.)
#include <stdio.h>
int main() {
int i=123;
FILE *fp;
int ret;
fp=fopen("123.txt", "w");
if (fp==NULL) {
printf("Kan file 123.txt niet openen!");
}
else {
ret=fprintf(fp, "%d", i);
if (ret==EOF) {
printf("Er is iets fout gegaan bij schrijven in file 123.txt!");
}
else {
printf("Er zijn %d karakters geschreven in file 123.txt!", ret);
}
fclose(fp);
}
getchar();
return 0;
}
De uitvoer van dit programma is als volgt:
In het directory waar de executable file is uitgevoerd is nu de file
123.txt
aangemaakt. In de filebrowser kunnen de "eigenschappen"
van deze file bekeken worden. De file blijkt 3 bytes groot te zijn. Deze
file kan met notepad worden bekeken:
![]() |
![]() |
Met een zogenaamde hexeditor kunnen we de inhoud van de file zowel in hexadecimale codering als in ASCII codering bekijken. Een eenvoudige hexeditor kun je downloaden vanaf: http://www.chmaas.handshake.de/delphi/freeware/xvi32/xvi32.htm.
In het deel met de witte achtergrond zien we de hex codes van de bytes uit de file. In het deel met de grijze achtergrond zien we de bijbehorende ASCII karakters. Het is nu duidelijk te zien dat de file bestaat uit 3 bytes. Er is geen end-of-file karakter! De drie bytes bevatten de ASCII codes voor karakter 1, karakter 2 en karakter 3.
fputs
en andere functies.
Er zijn nog meer functies gedeclareerd in stdio.h
om informatie
naar tekstfiles te kunnen schrijven, bijvoorbeeld
fputs
.
Deze functies worden hier niet verder behandeld maar kunnen via de link of
in de helpfile van Borland C++ 5.02 worden opgezocht.
Er zijn nog diverse andere functies beschikbaar in stdio.h
die
voor tekstfiles gebruikt kunnen worden:
feof
,
ferror
,
ffush
,
freopen
,
remove
,
rename
,
rewind
,
tmpfile
enz. Deze functies worden hier niet verder behandeld maar kunnen in de helpfile
van Borland C++ 5.02 of via de links worden opgezocht.
Je kunt de volgende bewerkingen op binairefiles uitvoeren:
Om een binairefile te kunnen lezen of beschrijven moet de file eerst geopend
worden. Dit gaat bijna hetzelfde als het openen van een
tekstfile alleen moet je bij de tweede parameter mode
de
letter b
toevoegen. Voorbeeld:
FILE *infile; infile=fopen("infile.dat", "rb");
Het boek gebruikt voor tekstfiles de extensie .txt
en voor
binairefiles de extensie .dat
. Bedenk echter dat het operating
systeem zich niets aantrekt van deze extensies. Je kunt een binairefile
dus rustig testfile.txt
noemen.
Het sluiten van een binairefile gaat exact hetzelfde als het sluiten van een tekstfile.
Een binairefile kan beschreven worden met de functie fwrite
.
Deze functie schrijft een aantal bytes in de file en is in de include file
stdio.h
als volgt gedeclareerd:
size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);
Als eerste parameter moet een pointer worden meegegeven naar de variabele
(of variabelen) die moet(en) worden weggeschreven. Als tweede parameter moet
de grootte van één variabele (in bytes) worden opgegeven. Meestal
wordt de operator sizeof
gebruikt om de grootte te bepalen.
Als derde parameter moet het aantal variabelen dat moet worden weggeschreven
worden meegegeven. (Het is alleen zinvol om een aantal > 1 op te geven
als de pointer ptr
wijst naar een array! Als vierde parameter
moet een FILE*
worden meegegeven die je hebt teruggekregen van
de functie fopen
.
De functie fwrite
geeft het aantal variabelen terug dat succesvol
is weggeschreven.
In het volgende voorbeeld wordt aan de integer
variabele i
de waarde 123
toegekend en daarna wordt
deze variabele weggeschreven in een binairefile. (Dit is natuurlijk volkomen
zinloos maar maakt wel duidelijk hoe het werkt.)
#include <stdio.h>
int main() {
int i=123;
FILE *fp;
size_t ret;
fp=fopen("123.bin", "wb");
if (fp==NULL) {
printf("Kan file 123.bin niet openen!");
}
else {
ret=fwrite(&i, sizeof i, 1, fp);
if (ret!=1) {
printf("Er is iets fout gegaan bij schrijven in file 123.bin!");
}
else {
printf("Er zijn %d variabelen geschreven in file 123.bin!", ret);
}
fclose(fp);
}
getchar();
return 0;
}
De uitvoer van dit programma is als volgt:
In het directory waar de executable file is uitgevoerd is nu de file
123.bin
aangemaakt. In de filebrowser kunnen de "eigenschappen"
van deze file bekeken worden. De file blijkt 4 bytes groot te zijn. Deze
file kan wel met notepad worden geopend maar je ziet dan "vreemde" karakters:
![]() |
![]() |
Met de hexeditor kunnen we de inhoud van de file zowel in hexadecimale codering als in ASCII codering bekijken.
In het deel met de witte achtergrond zien we de hex codes van de bytes uit de file. In het deel met de grijze achtergrond zien we de bijbehorende ASCII karakters. Het is nu duidelijk te zien dat de file bestaat uit 4 bytes. Er is geen end-of-file karakter! De vier bytes bevatten tesamen het 32 bits hexadecimale getal 0000007B. Dit komt overeen met de decimale waarde 123. Je ziet dat het minst significante byte als eerste in de file wordt geschreven (dit is afhankelijk van het operating systeem).
In het volgende voorbeeld zie je hoe met
één aanroep van write
een hele array met getallen
kan worden weggeschreven:
#include <stdio.h>
#define AANTAL 100
int main() {
int rij[AANTAL], i;
FILE *fp;
size_t ret;
for (i=0; i<AANTAL; ++i) {
rij[i]=i*i*i;
}
fp=fopen("getallen.bin", "wb");
if (fp==NULL) {
printf("Kan file getallen.bin niet openen!");
}
else {
ret=fwrite(&rij[0], sizeof rij[0], AANTAL, fp);
if (ret!=AANTAL) {
printf("Er is iets fout gegaan bij schrijven in file getallen.bin!");
}
else {
printf("Er zijn %d variabelen geschreven in file getallen.bin!", ret);
}
fclose(fp);
}
getchar();
return 0;
}
De expressie:
&rij[0]
kan vervangen worden door:
rij
omdat de naam van een array gebruikt kan worden als een pointer naar het eerste element van de array.
De uitvoer van dit programma is als volgt:
In het directory waar de executable file is uitgevoerd is nu de file
getallen.bin
aangemaakt. In de filebrowser kunnen de "eigenschappen"
van deze file bekeken worden. De file blijkt 400 bytes groot te zijn. Met
de hexeditor kunnen we de inhoud van de file zowel in hexadecimale codering
als in ASCII codering bekijken.
Een binairefile kan ingelezen worden met de functie fread
. Deze
functie leest een aantal bytes uit de file en is in de include file
stdio.h
als volgt gedeclareerd:
size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
Als eerste parameter moet een pointer worden meegegeven naar de variabele
(of variabelen) die moet(en) worden ingelezen. Als tweede parameter moet
de grootte van één variabele (in bytes) worden opgegeven. Meestal
wordt de operator sizeof
gebruikt om de grootte te bepalen.
Als derde parameter moet het aantal variabelen dat moet worden ingelezen
worden meegegeven. (Het is alleen zinvol om een aantal > 1 op te geven
als de pointer ptr
wijst naar een array! Als vierde parameter
moet een FILE*
worden meegegeven die je hebt teruggekregen van
de functie fopen
.
De functie fread
geeft het aantal variabelen terug dat succesvol
is ingelezen.
In het onderstaande programma wordt de hierboven
aangemaakte file getallen.bin
getal voor getal ingelezen en
naar het beeldscherm geschreven.
#include <stdio.h>
int main() {
int i;
FILE *fp;
fp=fopen("getallen.bin", "rb");
if (fp==NULL) {
printf("Kan file getallen.bin niet openen!");
}
else {
while (fread(&i, sizeof i, 1, fp)==1) {
printf("%10d", i);
}
fclose(fp);
}
getchar();
return 0;
}
Als je weet hoeveel getallen er maximaal in de file staan (en in dit geval weten we dat) kun je de hele file in één keer inlezen (in een array).
#include <stdio.h>
#define AANTAL 200
int main() {
int rij[AANTAL], i;
FILE *fp;
size_t ret;
fp=fopen("getallen.bin", "rb");
if (fp==NULL) {
printf("Kan file getallen.bin niet openen!");
}
else {
ret=fread(&rij[0], sizeof rij[0], AANTAL, fp);
if (ret==0) {
printf("Er is iets fout gegaan bij lezen uit file getallen.bin!");
}
else {
printf("Er zijn %d variabelen gelezen uit file getallen.bin!\n", ret);
}
for (i=0; i<ret; ++i) {
printf("%10d", rij[i]);
}
fclose(fp);
}
getchar();
return 0;
}
Merk op dat de array 200 integers kan bevatten terwijl de file maar 100 integers
bevat. Dit is echter geen probleem omdat de functie fread
het
aantal ingelezen getallen teruggeeft.
De uitvoer van dit programma is als volgt:
Je kunt in een binairefile ook zoeken (voor- en achteruit spoelen). De functie
fseek
kan gebruikt worden om de filepointer te verplaatsen en
is in de include file stdio.h
als volgt gedeclareerd:
int fseek(FILE *stream, long offset, int whence);
Als eerste parameter moet een FILE*
worden meegegeven die je
hebt teruggekregen van de functie fopen
. Als tweede parameter
moet een aantal bytes worden meegegeven dat je de filepointer wilt
verplaatsen. Als derde parameter moet de plaats in de file worden opgegeven
waarvandaan de offset
wordt opgegeven. Deze laatste parameter
mag maar 3 waarden hebben (die als symbolische constanten zijn gedefinieerd
in stdio.h
):
SEEK_SET |
De parameter offset geeft het aantal bytes vanaf het begin
van de file. In dit geval kun je een positieve waarde van offset
opgeven om de filepointer naar een bepaalde positie "door te spoelen". |
SEEK_CUR |
De parameter offset geeft het aantal bytes vanaf de huidige
positie van de filepointer. In dit geval kun je een positieve waarde van
offset opgeven om de filepointer "door te spoelen" maar ook
een negatieve waarde om de filepointer "terug te spoelen". |
SEEK_END |
De parameter offset geeft het aantal bytes vanaf het einde
van de file. In dit geval moet je een negatieve waarde van
offset opgeven om de filepointer "terug te spoelen". |
De functie fseek
geeft 0
terug als het verplaatsen
van de filepointer is gelukt. Let op! In DOS/Windows geeft fseek
echter ook 0
terug als de opgegeven positie niet bestaat (zie
de helpfile van Borland C++ 5.02 voor verdere informatie).
In het onderstaande voorbeeld wordt de hierboven
aangemaakte file getallen.bin
geopend en wordt de filepointer
met fseek
op het 11de getal geplaatst door 10 getallen
door te spoelen. Daarna wordt telkens met fread
1 getal gelezen
en worden met fseek
steeds 9 getallen overgeslagen.
#include <stdio.h>
int main() {
int i;
FILE *fp;
size_t res;
fp=fopen("getallen.bin", "rb");
if (fp==NULL) {
printf("Kan file getallen.bin niet openen!");
}
else {
if (fseek(fp, 10*sizeof i, SEEK_SET)!=0) {
printf("Er is iets fout gegaan bij zoeken in file getallen.bin!");
}
else {
while (fread(&i, sizeof i, 1, fp)==1) {
printf("%10d", i);
if (fseek(fp, 9*sizeof i, SEEK_CUR)!=0) {
printf("Er is iets fout gegaan bij zoeken in file getallen.bin!");
}
}
}
fclose(fp);
}
getchar();
return 0;
}
De uitvoer van dit programma is als volgt:
Een voorbeeld met binaire files en struct
's kun je
hier vinden.
Het verschil tussen tekstfiles en binairefiles is afhankelijk van het operating systeem. In UNIX/Linux blijkt er zelfs helemaal geen verschil te zijn!
In windows is het verschil minder groot als je uit het bovenstaande verhaal
begrepen zou kunnen hebben. Het enige verschil tussen tekstfiles en binairefiles
is dat bij het wegschrijven in tekstfiles het karakter '\n'
(hexadecimaal 0A
) wordt vervangen door twee karakters
'\r'
(hexadecimaal 0D
) en '\n'
(hexadecimaal 0A
). Bij het inlezen van een tekstfile worden
deze 2 karakters weer ingelezen als één '\n'
karakter.
Het volgende programma demonstreert dit:
#include <stdio.h>
int main() {
int c;
FILE *fp;
fp=fopen("tekstfile.txt", "w");
if (fp==NULL) {
printf("Kan file tekstfile.txt niet openen!");
}
else {
fprintf(fp, "Hallo\nDaar\n");
fclose(fp);
}
fp=fopen("binfile.bin", "wb");
if (fp==NULL) {
printf("Kan file binfile.bin niet openen!");
}
else {
fprintf(fp, "Hallo\nDaar\n");
fclose(fp);
}
getchar();
return 0;
}
Inhoud van tekstfile.txt
:
![]() |
![]() |
Inhoud van binfile.bin
:
![]() |
![]() |
Je kunt dus best met fread
en fwrite
werken in
een tekstfile maar je zult dan wel vreemde fouten krijgen omdat het wegschrijven
van een integer waar toevallig het hexadecimale byte 0A in voorkomt tot het
wegschrijven van een extra 0D zal leiden. Het volgende
programma demonstreert dit:
#include <stdio.h>
int main() {
int i=10;
FILE *fp;
fp=fopen("tekstfile.txt", "w");
if (fp==NULL) {
printf("Kan file tekstfile.txt niet openen!");
}
else {
fwrite(&i, sizeof i, 1, fp);
fclose(fp);
}
fp=fopen("binfile.bin", "wb");
if (fp==NULL) {
printf("Kan file binfile.bin niet openen!");
}
else {
fwrite(&i, sizeof i, 1, fp);
fclose(fp);
}
getchar();
return 0;
}
Inhoud van tekstfile.txt
:
Inhoud van binfile.bin
:
In UNIX en Linux wordt helemaal geen onderscheid gemaakt tussen tekstfiles
en binairefiles. Als je een '\n'
in een file schrijft wordt
altijd slechts één karakter in de file geschreven.