Vous êtes sur la page 1sur 22

Chæång 9

XUÁÚT NHÁÛP FILE

Xuáút nháûp file (File I/O) laì mäüt trong nhæîng khêa caûnh phæïc taûp nháút cuía báút kyì
ngän ngæî láûp trçnh naìo båíi vç noï gàõn boï máût thiãút våïi hãû âiãöu haình. Caïc hãû âiãöu
haình biãún âäøi nhiãöu daûng khaïc nhau âãø cho pheïp truy cáûp dæî liãûu trong caïc file
vaì caïc thiãút bë. Caïc sæû thay âäøi naìy taûo cho ta caïc khoï khàn âãø thiãút kãú caïc khaí
nàng xuáút/nháûp (I/O) maì coï tênh khaí chuyãøn tæì mäüt caìi âàût cuía mäüt ngän ngæî
láûp trçnh naìy sang mäüt ngän ngæî láûp trçnh khaïc.
Ngän ngæî C biãøu diãùn I/O thäng qua mäüt táûp ráút nhiãöu caïc haìm chuáøn. Nhiãöu
trong säú nhæîng haìm naìy âaî âæåüc mä taí láön âáöu tiãn trong chuáøn K&R. Mäüt säú
khaïc âæåüc ruït ra tæì thæ viãûn I/O cuía UNIX.
UÍy ban ANSI âaî kãút näúi 2 thæ viãûn naìy laûi, phaït triãøn mäüt säú haìm, loaûi boí âi
mäüt säú, vaì sæía âäøi nhæîng caïi coìn laûi. Trong thæ viãûn ANSI, táút caí caïc haìm I/O
âãöu phaíi sæí duûng bäü âãûm, ta cuîng coï khaí nàng thay âäøi kêch cåî bäü âãûm naìy.
Thãm vaìo âoï, caïc haìm I/O cuía ANSI taûo ra mäüt sæû khaïc biãût giæîa caïch truy cáûp
file åí chãú âäü nhë phán vaì åí chãú âäü vàn baín.
Thæ viãûn chuáøn cuía C chæïa gáön 40 haìm biãøu diãùn caïc pheïp toaïn I/O. Chuïng coï
thãø âæåüc chia thaình nhiãöu nhoïm.

9.1 CAÏC STREAM (LUÄÖNG XUÁÚT NHÁÛP)


C khäng taûo ra báút kyì mäüt sæû khaïc biãût naìo giæîa caïc thiãút bë, nhæ mäüt terminal
hoàûc mäüt äø âéa tæì, vaì caïc file âæåüc læu trãn âéa. Trong táút caí caïc træåìng håüp,
pheïp toaïn I/O âãöu âæåüc biãøu diãùn thäng qua caïc luäöng xuáút nháûp (streams) âæåüc
liãn kãút våïi file hoàûc thiãút bë. Mäüt stream chæïa daîy caïc byte coï thæï tæû. Ta coï thãø
nghé noï nhæ mäüt maíng mäüt chiãöu cuía caïc kyï tæû. Âoüc vaì ghi file hoàûc thiãút bë thç
âoï chênh laì âoüc dæî liãûu tæì stream hoàûc ghi dæî liãûu lãn stream.
C PROGRAM
FILE
STREAM

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 147


Chæång 9, Xuáút Nháûp File

Âãø biãøu diãùn caïc pheïp toaïn I/O, ta phaíi näúi kãút mäüt stream våïi mäüt haìm hay
mäüt thiãút bë. Ta coï thãø laìm âiãöu naìy bàòng caïch khai baïo mäüt con troí troí âãún mäüt
kiãøu cáúu truïc goüi laì FILE. Cáúu truïc FILE, âæåüc âënh nghéa åí stdio.h, chæïa mäüt
säú træåìng âãø læu caïc thäng tin nhæ tãn file, chãú âäü truy cáûp cuía noï, vaì mäüt con
troí troí âãún kyï tæû tiãúp theo trong stream. Caïc træåìng naìy seî âæåüc nháûn giaï trë khi
ta måí stream vaì truy cáûp âãún noï.
Cáúu truïc FILE cung cáúp cho hãû âiãöu haình thäng tin våïi caïc thäng tin giæî chäù,
nhæng ta chè coï thãø truy cáûp stream thäng qua mäüt phæång tiãûn âoï laì con troí troí
âãún cáúu truïc FILE, goüi laì con troí file. Con troí file læu giæî biãún stream âæåüc traí
vãö tæì haìm fopen(). Ta duìng con troí file âãø âoüc, ghi dæî liãûu hoàûc âoïng stream.
Mäüt chæång trçnh coï thãø coï nhiãöu hån mäüt stream måí âäöng thåìi, do duì mäùi caìi
âàût âãöu chè cho pheïp mäüt säú giåïi haûn caïc stream âæåüc måí.
Mäüt trong nhæîng træåìng cuía cáúu truïc FILE laì bäü âënh vë file (file position
indicator) noï chè âãún byte maì åí âoï kyï tæû kãú tiãúp seî âæåüc âoüc hoàûc ghi. Khi ta
âoüc vaì ghi file, hãû âiãöu haình âënh vë bäü chè vë trê file âãún con troí troí âãún byte
tiãúp theo. Traïnh nháöm láùn giæîa con troí file vaì bäü âënh vë file. Con troí file xaïc
âënh mäúi liãn kãút giæîa mäüt stream âaî måí våïi mäüt file hay thiãút bë. Bäü âënh vë
file tham chiãúu âãún mäüt vë trê byte trong mäüt stream.

9.1.1 CAÏC STREAM CHUÁØN (Standard Streams)


Trong C, coï 3 stream maì chuïng seî âæåüc tæû âäüng måí cho táút caí caïc chæång trçnh.
Tãn cuía chuïng laì stdin, stdout, stderr. Thäng thæåìng, caïc stream naìy chè âãún caïc
âáöu cuäúi (terminal), nhæng nhiãöu hãû âiãöu haình cho pheïp ta thay âäøi âiãöu naìy.
Chàóng haûn, ta coï thãø muäún caïc thäng baïo läùi âæåüc ghi ra mäüt file thay vç ra
terminal.
Caïc haìm xuáút nháûp maì ta âaî laìm quen, vê duû printf() vaì scanf(), sæí duûng caïc
stream màûc âënh naìy. printf() ghi ra stdout, vaì scanf() âoüc tæì stdin. Ta coï thãø
duìng caïc haìm naìy âãø biãøu diãùn I/O âãún file bàòng caïch cho stdin vaì stdout chè
âãún caïc file (sæí duûng haìm freopen() âãø laìm viãûc naìy). Mäüt phæång phaïp âån
giaín hån laì sæí duûng caïc haìm tæång âæång, âoï laì caïc daình cho I/O nhæ fprintf(),
fscanf(), nhæîng haìm naìy cho pheïp ta chè roî mäüt stream naìo âoï.

9.1.2 CAÏC ÂËNH DAÛNG VÀN BAÍN VAÌ NHË PHÁN


Dæî liãûu coï thãø âæåüc truy cáûp theo mäüt trong hai daûng: vàn baín vaì nhë phán. Mäüt
stream daûng vàn baín chæïa mäüt loaût caïc doìng, åí âoï mäùi doìng âæåüc kãút thuïc bàòng
kyï tæû newline. Tuy nhiãn caïc hãû âiãöu haình coï thãø coï nhiãöu caïch âãø læu giæî caïc
doìng lãn âéa tæì, vç váûy våïi mäùi doìng trong file vàn baín (text file) khäng cáön
Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 148
Chæång 9, Xuáút Nháûp File

thiãút kãút thuïc båíi mäüt kyï tæû newline. Nhæng khi caïc doìng naìy âæåüc âoüc vaìo bäü
nhåï trong chãú âäü vàn baín thç caïc haìm thæ viãûn seî tæû âäüng cheìn caïc kyï tæû
newline vaìo stream. Cuîng giäúng nhæ váûy, khi nhæîng doìng âæåüc ghi tæì mäüt
stream vàn baín ra mäüt thiãút bë læu træî, caïc haìm I/O coï thãø thay thãú caïc kyï tæû
newline trong stream bàòng caïc kyï tæû âaî âæåüc âënh nghéa træåïc goüi laì
implementation-defined characters. Bàòng caïch naìy, caïc stream vàn baín cuía C
coï mäüt sæû xuáút hiãûn thêch håüp æïng våïi caïc mäi træåìng, ngay caí khi âënh daûng
cuía dæî liãûu trãn säú caïc thiãút bë læu træî coï thãø khaïc nhau.
Våïi daûng nhë phán, trçnh biãn dëch khäng dæûa trãn sæû diãùn dëch cuía caïc byte. Noï
chè âån giaín laì âoüc vaì ghi caïc bit chênh xaïc nhæ laì baín thán chuïng. Caïc stream
nhë phán âæåüc sæí duûng phäø duûng cho caïc dæî liãûu khäng phaíi laì vàn baín, åí âáy
khäng coï caïc cáúu truïc doìng vaì âiãöu quan troüng laì noï giæî chênh xaïc näüi dung cuía
caïc file. Nãúu ta caím tháúy thuáûn tiãn hån khi giæî væîng caïc cáúu truïc doìng cuía file
thç nãn sæí duûng stream vàn baín. Ba stream chuáøn âãöu âæåüc måí dæåïi chãú âäü vàn
baín.

9.2 SÆÍ DUÛNG BÄÜ ÂÃÛM (BUFFERING)


Nãúu âem so saïnh våïi bäü nhåï, thç caïc thiãút bë læu træî thæï cáúp nhæ âéa tæì laì cæûc kyì
cháûm. Våïi háöu hãút caïc chæång trçnh I/O, thåìi gian âãø truy cáûp caïc thiãút bë seî
chiãúm ráút nhiãöu âãø CPU biãøu diãùn caïc pheïp toaïn âoï. Vç váûy âiãöu cæûc kyì quan
troüng laì laìm giaím säú láön âoüc vaì ghi thiãút bë caìng nhiãöu caìng täút. Viãûc sæí duûng
bäü âãûm laì mäüt caïch âån giaín nháút âãø thæûc hiãûn âiãöu naìy.
Bäü âãûm (buffer) laì mäüt vuìng maì åí âoï dæî liãûu âæåüc læu giæî taûm thåìi træåïc khi
âæåüc gåíi âãún âêch cuía noï. Sæí duûng bäü âãûm cung cáúp viãûc chuyãøn âäøi dæî liãûu
mäüt caïch hiãûu quaí båíi vç noï cho pheïp hãû âiãöu haình giaím thiãøu säú láön truy cáûp
caïc thiãút bë I/O.
Táút caí caïc hãû âiãöu haình âãöu sæí duûng bäü âãûm âãø âoüc vaì ghi dæî liãûu lãn caïc thiãút
bë I/O. Âoï laì, hãû âiãöu haình chè truy cáûp caïc thiãút bë I/O trong caïc khäúi coï kêch
thæåïc cäú âënh, goüi laì caïc block. Theo màûc âënh, mäüt block coï kêch thæåïc laì 512
byte hay 1024 byte. Âiãöu naìy coï nghéa laì ngay caí khi ta chè muäún âoüc mäüt kyï tæû
tæì file, hãû âiãöu haình cuîng âoüc toaìn bäü block chæïa kyï tæû âoï. Våïi caïc pheïp toaïn
âoüc dæî liãûu âån giaín thç âiãöu naìy khäng ráút hiãûu quaí, nhæng giaí sæí ta muäún âoüc
1000 kyï tæû tæì file, nãúu khäng duìng bäü âãûm, hãû thäúng phaíi biãøu diãùn 1000 pheïp
toaïn âënh vë âãún vaì âoüc dæî liãûu. Màût khaïc, nãúu xuáút nháûp duìng bäü âãûm, hãû
thäúng âoüc toaìn bäü mäüt block vaìo bäü nhåï räöi thç loaûi boí mäùi kyï tæû ra khoíi bäü nhåï
nãúu cáön thiãút, âiãöu naìy tiãút kiãûm âæåüc 999 pheïp toaïn I/O.

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 149


Chæång 9, Xuáút Nháûp File

Thæ viãûn thæûc hiãûn cuía C chæïa thãm mäüt låïp caïc caïch sæí duûng bäü âãûm dæåïi 2
daûng: line buffering vaì block buffering.
Trong line buffering, hãû thäúng seî læu caïc kyï tæû cho âãún khi mäüt kyï tæû newline
âæåüc âæa vaìo, hoàûc laì khi bäü âãûm âáöy, vaì räöi seî gæíi toaìn bäü doìng âãún hãû âiãöu
haình âãø xæí lyï.
Trong block buffering, hãû thäúng seî læu caïc kyï tæû cho âãún khi block âáöy, sau âoï
seî chuyãøn toaìn bäü block cho hãû âiãöu haình. Kêch cåî cuía block âæåüc xaïc âënh båíi
hãû diãöu haình, thæåìng laì 512 hay 1024 byte. Theo màûc âënh, táút caí I/O stream
chè âãún mäüt file sæí duûng bäü âãûm block.
Thæ viãûn I/O chuáøn cuía C coï gäöm mäüt bäü quaín lyï bäü âãûm (buffer manager) noï
giæî caïc bäü âãûm láu trong bäü nhåï. Vç váûy nãúu baûn truy xuáút cuìng mäüt pháön cuía
stream nhiãöu hån mäüt láön thç âáy laì cå häüi täút âãø hãû thäúng traïnh truy xuáút caïc
thiãút bë I/O nhiãöu láön. Tuy nhiãn, chuï yï ràòng âiãöu naìy coï thãø taûo ra váún âãö khi
file âoï âang âæåüc chia xeí cho nhiãöu tiãún trçnh.
Laìm saûch bäü âãûm cuía mäüt stream: int fflush(FILE *stream);

9.3 FILE DÁÙN HÆÅÏNG <stdio.h>


Âãø sæí duûng caïc haìm I/O, ta phaíi âæa cáu lãûnh âãø naûp file dáùn hæåïng <stdio.h>.
File naìy chæïa caïc thäng tin sau:
• Khai baïo nguyãn máùu cho caïc haìm xuáút nháûp
• Khai baïo cáúu truïc FILE
• Nhiãöu macro hàòng hæîu duûng, bao gäöm stdin, stdout, stderr.
Mäüt macro quan troüng khaïc laì EOF, âáy laì giaï trë traí vãö cuía ráút nhiãöu haìm khi
hãû thäúng bàõt gàûp dáúu hiãûu cuäúi file (end-of-file). Kyï tæû NULL âæåüc Uíy ban
ANSI âënh nghéa trong mäüt file dáùn hæåïng coï tãn laì stddef.h. Âãø sæí duûng NULL
maì khäng cáön phaíi khai baïo naûp stddef.h ta chè cáön âënh nghéa laûi nhæ sau:
#ifndef NULL
#define NULL (void *) 0
#endif

9.4 MÅÍ VAÌ ÂOÏNG MÄÜT FILE


9.4.1 KHAI BAÏO MÄÜT BIÃÚN FILE
Âãø khai baïo mäüt biãún file ta duìng cuï phaïp sau

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 150


Chæång 9, Xuáút Nháûp File

FILE * <biãún file >;


Vê duû:
#include <stdio.h>
FILE *file_var;

9.4.2 MÅÍ MÄÜT FILE


Træåïc khi ta coï thãø âoüc hay ghi dæî liãûu lãn mäüt file thç ta phaíi måí noï ra bàòng
haìm fopen().
Khai baïo nguyãn máùu:
FILE *fopen(const char *fname, const char *mode);
Haìm fopen() nháûn hai âäúi säú, âäúi säú thæï nháút laì tãn file (fname), âäúi säú thæï hai
laì chãú âäü truy xuáút file (mode). Coï hai chãú âäü truy xuáút file: mäüt daình cho caïc
stream vàn baín, mäüt daình cho caïc stream nhë phán. Caïc stream vàn baín seî âæåüc
måí theo caïc mode âæåüc chè ra dæåïi âáy.
Caïc chãú âäü truy xuáút file: const char *mode
“r” Måí mäüt file vàn baín âaî coï sàôn âãø âoüc. Viãûc âoüc
bàõt âáöu taûi vê trê âáöu cuía file.
“w” Taûo måïi mäüt file vàn baín âãø ghi. Nãúu file coï coï
trãn âéa thç noï seî ghi âeì, tæïc laì chè coìn file räùng.
Bäü chè âënh vë trê seî khåíi âäüng åí âáöu file.
“a” Måí mäüt file vàn baín âaî coï sàôn âãø bäø sung. Ta
chè coï thãø ghi dæî liãûu chè åí vë trê cuäúi file. Ngay
caí khi ta di chuyãøn vë trê cuía bäü âënh vë thç viãûc
ghi cuîng xuáút hiãûn åí cuäúi file.
“r+” Måí mäüt file vàn baín âaî coï sàôn âãø âoüc vaì ghi dæî
liãûu. Bäü âënh vë trê seî âæåüc khåíi âäüng âãún âáöu
file.
“w+” Taûo måïi mäüt file vàn baín âãø âoüc vaì ghi dæî liãûu.
Nãúu file âaî coï thç seî bë ghi âeì.
“a+” Måí mäüt file âaî täön taûi hoàûc taûo måïi mäüt file åí
chãú âäü bäø sung. Ta coï thãø âoüc dæî liãûu åí báút kyì
âáu trãn file nhæng chè coï thãø ghi dæî liãûu åí cuäúi
file.

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 151


Chæång 9, Xuáút Nháûp File

Caïc stream nhë phán thç cuîng hoaìn toaìn giäúng nhæ váûy, nhæng chè thãm vaìo
cuäúi chuäùi naìy mäüt kyï tæû b. Vê duû âãø måí mäüt file nhë phán âãø âoüc thç ta duìng
nhæ sau “rb”, coìn våïi vàn baín ta cuîng coï thãø thãm vaìo kyï tæû t cuäúi, chàóng haûn
“rt”.
Toïm tàõt caïc thuäüc tênh chãú âäü cuía fopen()

r w a r+ w+ a+
File phaíi coï træåïc khi måí 9 9
File cuî seî bë xoaï hãút näüi dung 9 9
Stream coï thãø âoüc 9 9 9 9
Stream coï thãø viãút 9 9 9 9 9
Stream chè coï thãø viãút åí cuäúi 9 9

Haìm fopen() traí vãö mäüt con troí file nãúu viãûc måí thaình cäng, ngæåüc laûi seî traí vãö
con troí NULL.
Vê duû: Haìm sau âãø måí mäüt file coï tãn chè roî, våïi chãú âäü truy xuáút naìo âoï.
#include <stdio.h>
#include <stddef.h>

FILE *open_file(char *fn, char *mode)


{
FILE *fp;

if ((fp = fopen(fn, mode))==NULL)


fprintf(stderr, "Läùi måí file %s våïi
chãú âäü truy xuáút laì %s\n", fn, mode);
return fp;
}

Duìng haìm naìy âãø måí file test.c theo chãú âäü âoüc.
#include <stdio.h>
#include <stddef.h>

main()
{
extern FILE *open_file();

if (open_file("test.c", "r")==NULL) exit(1);

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 152


Chæång 9, Xuáút Nháûp File

.
.
}

9.4.3 ÂOÏNG MÄÜT FILE


Âãø âoïng mäüt file, ta duìng haìm fclose()
int *fclose( FILE *fp );
Haìm traí vãö 0 nãúu thaình cäng, EOF (-1) nãúu khäng thaình cäng. fp laì con troí file
âæåüc traí vãö thäng qua haìm fopen() træåïc âoï.
Viãûc âoïng file seî giaíi phoïng cáúu truïc FILE maì con troí fp âang chè âãún, vç thãú hãû
âiãöu haình seî duìng cáúu truïc naìy cho file khaïc vaì noï cuîng xoaï saûch caïc bäü âãûm
liãn quan âãún noï. Háöu hãút caïc hãû âiãöu haình âãöu cho pheïp taûi mäüt thåìi âiãøm chè
coï thãø måí âæåüc mäüt säú file giåïi haûn, âáy laì mäüt âiãöu hay âãø âoïng file khi âaî
hoaìn thaình cäng viãûc våïi file âoï. Trong báút kyì træåìng håüp naìo, táút caí caïc stream
âang måí seî âæåüc âoïng khi chæång trçnh kãút thuïc.

9.5 ÂOÜC VAÌ GHI DÆÎ LIÃÛU


Sau khi måí file, ta sæí duûng con troí file âãø biãøu diãùn caïc thao taïc âoüc vaì ghi. Coï
3 cáúp âäü cho viãûc xuáút nháûp. Âoï laì ta coï thãø biãøu diãùn caïc thao taïc xuáút nháûp
theo 3 kêch cåî khaïc nhau cuía caïc âäúi tæåüng. Ba cáúp âäü âoï laì:
• Âoüc / ghi tæìng kyï tæû
• Âoüc / ghi tæìng doìng
• Âoüc / ghi tæìng block

9.5.1 ÂOÜC GHI TÆÌNG KYÏ TÆÛ


Coï 2 haìm âãø thæûc hiãûn viãûc âoüc ghi dæî liãûu lãn mäüt stream
fgetc( int ch, FILE *stream ) Haìm âoüc mäüt kyï tæû tæì mäüt stream
fputc( int ch, FILE *stream ) Haìm ghi mäüt kyï tæû ra mäüt stream

Vê duû: Sæí duûng getc() vaì putc() âãø sao cheïp file
#include <stdio.h>
#include <stddef.h>
#define FAIL 0
#define SUCCESS 1

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 153


Chæång 9, Xuáút Nháûp File

int copyfile(char *infile, char *outfile)


{
FILE *fp1, *fp2;

if ((fp1=fopen(infile, "rb"))==NULL)
return FAIL;
if ((fp2=fopen(outfile, "wb"))==NULL)
{
fclose(fp1);
return FAIL;
}

while (!feof(fp1))
fputc(fgetc(fp1), fp2);

fclose(fp1);
fclose(fp2);
return SUCCESS;
}

Ta måí caí hai file theo chãú âäü nhë phán båíi vç ta chè âoüc trãn tæìng kyï tæû riãng leí
maì khäng quan tám âãún cáúu truïc doìng cuía file. Haìm naìy thæûc hiãûn âæåüc trãn táút
caí caïc loaûi file.

9.5.2 ÂOÜC GHI TÆÌNG DOÌNG


Mäüt caïch khaïc âãø viãút haìm copyfile() åí trãn laì duìng caïch âoüc vaì ghi theo doìng
thay vç tæìng kyï tæû. Hai haìm sau duìng cho viãûc naìy fgets() vaì fputs(), coï khai
baïo nguyãn máùu nhæ sau:
char *fgets (char *s, int n, FILE *stream);
char *fputs (char *s, FILE *stream);
ÅÍ âáy:
s: con troí troí âãún pháön tæí âáöu cuía chuäùi
n: Säú nguyãn âaûi diãûn cho säú låïn nháút caïc kyï tæû âæåüc âoüc
stream: stream seî âæåüc âoüc.
fgets() âoüc caïc kyï tæû cho âãún khi gàûp mäüt lyï tæû newline, mäüt kyï tæû end-of-file,
hoàûc âaî âãún säú kyï tæû låïn nháút chè ra. fgets() tæû âäüng thãm mäüt kyï tæû null vaìo sau

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 154


Chæång 9, Xuáút Nháûp File

kyï tæû cuäúi cuìng cuía maíng. Haìm fputs() ghi mäüt maíng chè båíi âäúi säú âáöu tiãn
âãún mäüt stream åí âäúi säú thæï hai.
Vê duû: Viãút laûi haìm copyfile()
#include <stdio.h>
#include <stddef.h>
#define FAIL 0
#define SUCCESS 1
#define LINESIZE 100

int copyfile(char *infile, char *outfile)


{
FILE *fp1, *fp2;
char line[LINESIZE];

if ((fp1=fopen(infile, "r"))==NULL)
return FAIL;
if ((fp2=fopen(outfile, "w"))==NULL)
{
fclose(fp1);
return FAIL;
}

while (fgets(line, LINESIZE-1, fp1)!= NULL)


fputs(line, fp2);
fclose(fp1);
fclose(fp2);
return SUCCESS;
}

Chuï yï ràòng åí âáy ta måí file theo daûng vàn baín vç ta muäún truy xuáút dæî liãûu theo
tæìng doìng mäüt. Nãúu måí file daûng nhë phán thç haìm trãn coï thãø khäng laìm viãûc
âuïng.

9.5.3 ÂOÜC GHI TÆÌNG BLOCK


Ngoaìi hai caïch truy xuáút file nhæ trãn, ta cuîng coï thãø truy xuáút dæî liãûu theo tæìng
cuûm goüi laì block. Ta coï thãø nghé mäüt block nhæ laì mäüt maíng. Khi âoüc hay ghi
mäüt block, ta cáön phaíi chè roî säú caïc pháön trong block vaì kêch cåî cuía mäùi pháön
tæí. Hai haìm nháûp xuáút våïi block laì fread() vaì fwrite(), coï khai baïo nguyãn máùu
nhæ sau:

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 155


Chæång 9, Xuáút Nháûp File

size_t fread (void *ptr, size_t size, size_t nmemb,


FILE *stream);
size_t fwrite(void *ptr, size_t size, size_t nmemb,
FILE *stream);
ÅÍí âáy size_t laì mäüt kiãøu säú nguyãn âënh nghéa trong <stdio.h>.
ptr Con troí troí âãún maíng læu dæî liãûu
size Kêch cåî cuía mäùi pháön tæí trong maíng
nmemb Säú pháön tæí seî âoüc / ghi
stream Con troí file
fread() traí vãö säú pháön tæí âoüc âæåüc.
Haìm fwrite() traïi laûi våïi fread(). Noï cuîng nháûn caïc âäúi säú nhæ fread() nhæng
thay vç âoüc dæî liãûu tæì stream thç noï laûi ghi dæî liãûu ra stream.
Vê duû: Viãút laûi haìm copyfile() duìng fread() vaì fwrite().

#include <stdio.h>
#include <stddef.h>
#define FAIL 0
#define SUCCESS 1
#define BLOCKSIZE 512

typedef char DATA;


int copyfile(char *infile, char *outfile)
{
FILE *fp1, *fp2;
DATA block[BLOCKSIZE];
int num_read;

if ((fp1=fopen(infile, "rb"))==NULL)
return FAIL;
if ((fp2=fopen(outfile, "wb"))==NULL)
{
fclose(fp1);
return FAIL;
}

while ((num_read=fread(block, sizeof(DATA),


BLOCKSIZE, fp1))==BLOCKSIZE)
fwrite(block, sizeof(DATA), num_read, fp2);

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 156


Chæång 9, Xuáút Nháûp File

fwrite(block, sizeof(DATA), num_read, fp2);

fclose(fp1);
fclose(fp2);
return SUCCESS;
}

Vê duû aïp duûng: 1. Âoüc mäüt file chæïa caïc thäng tin vãö nhán viãn nhæ cáúu truïc
NHANVIEN åí Chæång 8 coï tãn “AG.REC” vaìo mäüt danh saïch liãn kãút.

static NHANVIEN *head;

int *read_file()
{
FILE *fp;
NHANVIEN *pnew;

if ((fp=fopen("AG.REC", "rb")==NULL)
return FAIL;
else
{
pnew=(NHANVIEN *)malloc(sizeof(NHANVIEN);
head= pnew;
while (fread(pnew, sizeof(NHANVIEN),
1, fp))==1)
{
pnew = pnew->next;
pnew = (NHANVIEN *)
malloc(sizeof(NHANVIEN);
}

fclose(fp);
return SUCCESS;
}

2. Ghi danh saïch ra file AG.REC


static NHANVIEN *head;

int write_file()
{
FILE *fp;
Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 157
Chæång 9, Xuáút Nháûp File

NHANVIEN *p;
int n=0;

if ((fp=fopen("AG.REC", "rb")==NULL)
return FAIL;
for (p=head; p->next!=NULL; n++, p=p->next);

if (n<1){
printf("Danh saïch räùng\n");
exit(1);
}
else
{
fwrite(head, sizeof(NHANVIEN), n, fp);
fclose(fp);
printf("Säú baín ghi: %d\n", n);
}

return SUCCESS;
}

9.5.4 XUÁÚT NHÁÛP COÏ ÂËNH DAÛNG


Sæí duûng hai haìm sau:
int fprintf (FILE *stream, const char *format
[, arg, ...]);
int fscanf (FILE *stream, const char *format,
address, ...);
Vê duû:
#include <stdio.h>
#include <stdlib.h>

int main()
{
int i;

printf("Nháûp mäüt säú nguyãn: ");


if (fscanf(stdin, "%d", &i))
fprintf(stdout, "Säú nguyãn nháûp vaìo
laì %d",i);
else

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 158


Chæång 9, Xuáút Nháûp File

fprintf(stderr, "Läùi âoüc säú tæì stdin");

return 0;
}

9.6 XUÁÚT NHÁÛP KHÄNG BÄÜ ÂÃÛM (Unbufered I/O)


Màûc duì viãûc sæí duûng bäü âãûm laì hiãûu quaí hån viãûc xæí lyï tæìng kyï tæû âån leí, thç
chuïng váùn khäng thoía maîn nãúu ta muäún tæìng kyï tæû mäüt âæåüc xæí lyï nhæ laì khi
noï âæåüc xuáút hay nháûp. Vê duû, ta muäún xæí lyï caïc kyï tæû nhæ khi chuïng âæåüc goî
vaìo hån laì phaíi âåüi âãún khi mäüt kyï tæû newline âæåüc âæa vaìo. C cho pheïp tàõt cå
chãú bäü âãûm bàòng caïch thay âäøi giaï trë màûc âënh cuía bäü âãûm.
Âãø tàõt sæí duûng bäü âãûm, ta coï thãø duìng setbuf() hoàûc setvbuf(). Haìm setbuf()
nháûn hai âäúi säú: âäúi säú âáöu tiãn laì mäüt con troí file, âäúi säú thæï hai laì mäüt con troí
troí âãún maíng kyï tæû âæåüc duìng nhæ bäü âãûm måïi. Nãúu con troí maíng laì con troí
null thç viãûc sæí duûng bäü âãûm seî tàõt âi, giaí sæí nhæ:
setbuf( stdin, NULL );
Haìm setbuf() khäng traí vãö giaï trë.
Haìm setvbuf() cuîng tæång tæû nhæ setbuf(), nhæng phæïc taûp hån mäüt tê. Noï nháûn
thãm hai âäúi säú næîa cho pheïp ta chè roî kiãøu bäü âãûm (line hoàûc block hoàûc
khäng) vaì kêch cåî cuía maíng âæåüc duìng laìm bäü âãûm. Kiãøu bäü âãûm laì mäüt trong
caïc kyï hiãûu sau (âënh nghéa trong stdio.h)
_IOFBF block buffering
_IOLBF line buffering
_IONBF no buffering
Vç váûy âãø tàõt bäü âãûm, ta viãút:
stat = setvbuf( stdin, NULL, _IONBF, 0 );
Haìm setvbuf() traí vãö giaï tri khaïc khäng nãúu thaình cäng.

9.7 TRUY XUÁÚT NGÁÙU NHIÃN


Caïc vê duû âãö cáûp åí caïc pháön træåïc giåïi thiãûu caïch truy xuáút file tuáön tæû. Trong
nhiãöu æïng duûng ta cáön truy xuáút caïc byte âàûc biãût åí giæîa file, trong nhæîng
træåìng håüp naìy âiãöu thæûc sæû hæîu duûng khi duìng caïc haìm truy xuáút ngáùu nhiãn
âoï laì fseek() vaì ftell().

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 159


Chæång 9, Xuáút Nháûp File

Haìm fseek() di chuyãøn bäü âënh vë trê file âãún mäüt kyï tæû âæåüc chè ra trong mäüt
stream. Khai baïo nguyãn máùu fseek() laì:
fseek(FILE *stream, long int kh_cach, int vi_tri);
Ba âäúi säú laì:
stream Con troí file
kh_cach Mäüt khoaíng caïch âæåüc âo theo caïc kyï tæû (coï thãø dæång
hoàûc ám)
vi_tri Vë trê khåíi âáöu âæåüc tênh
Coï ba trë säú âæåüc choün cuía vi_tri:
SEEK_SET Vë trê bàõt âáöu file
SEEK_CUR Vë trê hiãûn thåìi cuía bäü âënh vë file
SEEK_END Vë trê cuäúi file

Vê duû, cáu lãûnh


stat = fseek(fp, 10, SEEK_SET);
di chuyãøn bäü chè vë trê âãún kyï tæû thæï 10 trong stream. Kyï tæû tiãúp theo seî âæåüc
âoüc hoàûc ghi. Chuï yï ràòng caïc stream, cuîng giäúng nhæ maíng, bàõt âáöu taûi vë trê 0
nãn kyï tæû 10 chênh laì kyï tæû thæï 11 trong stream.
Giaï trë traí vãö cuía fseek() laì 0 nãúu yãu cáöu håüp lãû; nãúu yãu cáöu khäng håüp lãû
fseek() seî traí vãö mäüt giaï trë khaïc 0. Âiãöu naìy xaíy ra do nhiãöu lyï do. Vê duû nãúu fp
âæåüc måí theo chãú âäü chè âoüc, sau âoï noï cäú gàõng di chuyãøn bäü âënh vë file vãö sau
vë trê cuäúi file, âiãöu naìy laì khäng håüp lãû.
stat = fseek(fp, 1, SEEK_END);
Nãúu SEEK_END âæåüc sæí duûng trong caïc file chè âoüc, thç giaï trë khoaíng caïch
phaíi beï hån hay bàòng 0. Cuîng giäúng nhæ váûy nãúu duìng SEEK_SET thç giaï trë
khoaíng caïch phaíi låïn hån hay bàòng 0.
Våïi caïc stream nhë phán, âäúi säú khoaíng caïch coï thãø nháûn giaï trë nguyãn ám
hoàûc nguyãn dæång nhæng âæìng âáøy bäü âënh vë ra ngoaìi file. Våïi caïc stream
vàn baín thç âäúi säú khoaíng caïch phaíi laì 0 hoàûc laì giaï trë traí vãö cuía ftell().
Haìm ftell() chè nháûn mäüt âäúi säú, âoï laì mäüt con troí file. Haìm traí vãö vë trê hiãûn
thåìi cuía bäü chè vë trê. ftell() âæåüc duìng thæåìng laì traí vãö vë trê file sau khi thæûc
hiãûn mäüt säú pheïp toaïn I/O.

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 160


Chæång 9, Xuáút Nháûp File

Chuï yï ràòng vë trê traí vãö cuía ftell() âæåüc tênh tæì âáöu file. Våïi caïc stream nhë phán,
giaï trë traí vãö cuía ftell() âaûi diãûn cho säú kyï tæû tháût sæû kãø tæì âáöu file. Våïi caïc
stream vàn baín giaï trë traí vãö cuía ftell() laì caïc giaï trë caìi âàût âæåüc âaî âënh nghéa
maì chuïng chè coï yï nghéa khi sæí duûng laì giaï trë khoaíng caïch trong mäüt låìi goüi
fseek().
AÏp duûng xáy dæûng haìm filesize() âãø tênh kêch cåî file
long filesize(FILE *stream)
{
long curpos, length;

curpos = ftell(stream);
fseek(stream, 0L, SEEK_END);
length = ftell(stream);
fseek(stream, curpos, SEEK_SET);

return length;
}
Ngoaìi haìm fseek() âãø âënh vë âãún vë trê kyï tæû báút kyì trong mäüt stream, ta coï
thãm haìm rewind() âãø âæa bäü chè vë trê vãö âáöu file.
void rewind(FILE *stream);
Låìi goüi haìm sau
rewind( fp );
laì tæång âæång våïi
(void)fseek( fp, 0L, SEEK_SET );
Nhæng åí âáy coï mäüt âiãøm khaïc laì: rewind() xoaï âi maî läùi vaì end-of-file cho caïc
stream vaì khäng traí vãö giaï trë.

9.8 XÆÍ LYÏ LÄÙI XUÁÚT NHÁÛP


Mäùi haìm I/O âãöu traí vãö mäüt giaï trë âàûc biãût nãúu coï läùi xuáút hiãûn. Tuy nhiãn giaï
trë läùi cuía mäùi haìm laì khaïc nhau. Mäüt säú haìm traí vãö giaï trë 0, mäüt säú khaïc traí vãö
giaï trë khaïc 0, vaì mäü säú laûi traí vãö giaï trë EOF.
Trong cáúu truïc FILE coï hai træåìng ghi laûi maî läùi hoàûc giaï trë end-of-file cho mäùi
stream âang måí. Âiãöu kiãûn end-of-file âæåüc biãøu diãùn khaïc nhau våïi caïc hãû
thäúng khaïc nhau. Mäüt säú hãû thäúng duìng mäüt kyï tæû âàûc biãût âãø âënh vë trê cuäúi
file, trong khi caïc hãû thäúng khaïc duìng phæång phaïp âãúm kyï tæû âãø xaïc âënh khi
naìo âãún vë trê end-of-file. Mäüt vë trê end-of-file vaì mäüt cåì läùi cuía mäüt stream

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 161


Chæång 9, Xuáút Nháûp File

âæåüc kiãøm tra thäng hai haìm feof() vaì ferror(). Trong mäüt vaìi træåìng håüp mäüt
haìm I/O traí vãö cuìng mäüt giaï trë våïi end-of-file vaì maî läùi. Trong nhæîng træåìng
håüp naìy ta cáön kiãøm tra mäüt trong nhæîng cåì läùi âãø xem sæû kiãûn naìo thæûc sæû âaî
xuáút hiãûn.
Caïc haìm sau âáy kiãøm tra cåì läùi vaì cåì end-of-file cho mäüt stream âæåüc chè ra vaì
traí vãö mäüt trong bäún giaï trë càn cæï trãn caïc kãút quaí: haìm clearerr() thiãút láûp caí
hai giaï trë cåì vãö 0. Ta phaíi chuí âäüng thiãút láûp caïc giaï trë cåì bàòng clearerr(),
chuïng seî khäng tæû âäüng thiãút láûp laûi khi ta âoüc chuïng, chuïng cuîng khäng tæû
thiãút láûp vãö 0 nãúu coï caïc låìi goüi I/O kãú tiãúp. Chuïng âæåüc khåíi âäüng bàòng 0 khi
stream måí, nhæng chè coï mäüt caïch âãø thiãút láûp laûi chuïng vãö 0 bàòng clearerr().
Vê duû:
/* Nãúu caí hai cåì khäng thiãút láûp thç stat = 0.
* Nãúu cåì läùi, nhæng khäng phaíi eof, stat = 1.
* Nãúu cåì eof, nhæng khäng phaíi läùi, stat = 2.
* Nãúu caí hai cåì âæåüc thiãút láûp, thç stat = 3.
*/
#include <stdio.h>
#define EOF_FLAG 1
#define ERR_FLAG 2

char stream_stat(FILE *fp)


{
char stat = 0;
if (ferror(fp))
stat |= ERR_FLAG;
if (feof(fp))
stat |= EOF_FLAG;
clearerr();
return stat;
}
Ngoaìi ra ta coï mäüt haìm âãø in ra thäng baïo läùi:
void perror ( const char *msg );
msg laì mäüt chuäùi thäng baïo træåïc khi thäng baïo läùi
Vê duû: Giaí sæí file PERROR.DAT chæa coï trãn âéa
#include <stdio.h>
main()
{

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 162


Chæång 9, Xuáút Nháûp File

FILE *fp;
fp = fopen("PERROR.DAT", "r");

if (!fp)
perror("Khäng thãø måí file\n");
return 0;
}

Khäng thãø måí file: No such file or directory

# BIÃÚN errno
Ngoaìi hai cåì baïo end-of-file vaì läùi, coìn coï thãm mäüt biãún toaìn cuûc coï tãn errno
âæåüc sæí duûng båíi mäüt säú êt caïc haìm I/O âãø ghi caïc läùi. Âáy laì sæû kãú thæìa tæì
UNIX, errno laì mäüt biãún nguyãn âënh nghéa trong errno.h. Biãún errno âæåüc
duìng chuí yãúu cho caïc haìm toaïn hoüc; ráút êt caïc haìm I/O sæí duûng errno.

9.9 QUAÍN LYÏ FILE


Ta coï mäüt säú haìm quaín lyï file nhæ sau:
int remove( const char *file_name );
Xoaï mäüt file âæåüc chè ra båíi tãn. File bë xoaï phaíi âoïng. Haìm traí vãö 0 nãúu xoaï
thaình cäng, ngæåüc laûi seî traí vãö mäüt giaï trë khaïc 0.
int rename( const char *old, const char *new );
Âäøi tãn mäüt file âæåüc chè åí old sang tãn måïi new. Tãn måïi phaíi chæa coï trãn
âéa. Haìm traí vãö 0 nãúu thaình cäng, khaïc 0 nãúu khäng thaình cäng.

9.10 XUÁÚT NHÁÛP HÃÛ THÄÚNG


9.10.1 CAÏC HAÌM XUÁÚT NHÁÛP HÃÛ THÄÚNG
Måí file
int open( const char *fn, int access [,int mode]);
Måí mäüt file theo caïc caïch truy cáûp vaì caïc mode.
access YÏ nghéa
O_RONLY Måí file âãø âoüc
O_WONLY Måí file âãø ghi

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 163


Chæång 9, Xuáút Nháûp File

O_RDWR Måí file âãø âoüc vaì ghi


O_APPEN Måí file bäø sung
O_CREAT Taûo file
O_TEXT File text (duìng bäø sung)
O_BINARY File nhë phán (duìng bäø sung)

mode YÏ nghéa
S_IREAD Cho pheïp âoüc
S_IWRITE Cho pheïp ghi
S_IWRITE | S_IREAD Cho pheïp âoüc vaì ghi
Traí vãö giaï trë khäng ám nãúu thaình cäng, vaì âoï chênh laì giaï trë âãø truy cáûp lãn
file væìa måí. Nãúu läùi, seî traí vãö -1 (EOF).
Vê duû: Taûo file text våïi open()
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>

int main(void)
{
int handle;
char msg[] = "Hello world";

if ((handle = open("TEST.$$$",
O_CREAT | O_TEXT)) == -1)
{
perror("Error:");
return 1;
}
write(handle, msg, strlen(msg));
close(handle);
return 0;
}

Âoüc vaì Ghi file


int read ( int handle, void *buf, int size );
int write( int handle, void *buf, int size );
Chuï yï: handle = open(...)

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 164


Chæång 9, Xuáút Nháûp File

Xoaï file
int unlink( const char *file_name );
Xoaï mäüt file khoíi thæ muûc âæåüc chè ra

Truy xuáút ngáùu nhiãn file


long int lseek( int handle, long int offset,
int start );
Giaï trë start nháûn laì 0, 1, 2 tæång æïng nhæ trãn.

Âoïng file
close( int handle );

9.10.2 VÊ DUÛ
Viãút chæång trçnh thæûc hiãûn tæång tæû lãûnh COPY cuía DOS.
#include <fcntl.h>
#include <sys\stat.h>
#define BUF_SIZE 4096

char buff[BUF_SIZE];

int main(int argc, char *argv[])


{
int ihandle, ohandle, bytes;

if (argc != 3) {
printf("Usage: %s <source> <dest>\n",
argv[0]);
exit(1);
}
if ((ihandle = open(argv[1],
O_RDWR | O_BINARY)) == -1)
{
perror("Error:");
exit(1);
}
if ((ohandle = open(argv[2],O_CREAT |
O_WONLY | O_BINARY, S_IWRITE)) == -1)

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 165


Chæång 9, Xuáút Nháûp File

{
perror("Error:");
exit(1);
}
while ((bytes = read(ihandle, buff,
BUF_SIZE))>0)
write(ohandle, buff, bytes);
close(ihandle);
close(ohandle);
return 0;
}

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 166


Chæång 9, Xuáút Nháûp File

BAÌI TÁÛP

1. Viãút chæång trçnh coï sæí duûng cáu lãûnh tiãön xæí lyï #include.

2. Viãút mäüt haìm goüi laì compress() âãø xoïa táút caí caïc khoaíng tràõng thæìa tæì mäüt
file nguäön C. (Chuï yï ràòng: khäng xoïa caïc khoaíng tràõng trong hàòng kyï tæû
vaì hàòng chuäùi).

3. Viãút chæång trçnh âãø kiãøm tra tênh âuïng âàõn cuía caïc càûp dáúu ngoàûc vaì moïc
trong mäüt file nguäön C.

4. Viãút chæång trçnh âãø âãúm säú caïc kyï tæû, caïc tæì, vaì caïc doìng trong mäüt file.

5. Viãút chæång trçnh âãø copy táút caí caïc file trãn doìng lãûnh ra stdout.

6. Viãút chæång trçnh cho pheïp NSD nháûp dæî liãûu vaìo file chæïa caïc cáúu truïc
VITALSTAT âæåüc âënh nghéa åí chæång 8.

7. Viãút chæång trçnh âoüc caïc kyï tæû tæì thiãút bë nháûp chuáøn (standard input) vaì
sao cheïp ra thiãút bë xuáút chuáøn (standard output), chuyãøn mäùi chuäùi ‘\r’ ‘\n’
thaình ‘\n’.

8. Viãút chæång trçnh tæång tæû baìi 7, nháûn hai âäúi säú doìng lãûnh:

-from srcstr
-to deststr

Mäùi xuáút hiãûn cuía srcstr åí doìng dæî liãûu vaìo seî âæåüc chuyãøn thaình deststr åí
doìng dæî liãûu ra.

9. Viãút chæång trçnh måí mäüt file âæåüc chè ra åí doìng lãûnh vaì in maìn hçnh theo
thæï tæû ngæåüc laûi (âaío nngæåüc näüi dung file).

10. Viãút chæång trçnh âãø âoüc báút kyì file naìo trãn doìng lãûnh (ngay caí file nhë
phán) vaì in ra chè nhæîng daîy coï êt nháút hai kyï tæû thuäüc nhoïm caïc kyï tæû in
âæåüc ( ‘a’... ‘z’, ‘A’...‘Z’, ' ', ‘0’...‘9’).

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 167


Chæång 9, Xuáút Nháûp File

Giaïo Trçnh Ngän Ngæî Láûp Trçnh C 168

Vous aimerez peut-être aussi