Bài 21 Qu n lý t p tin
M c tiêu:
K t thúc bài h c này, b n có th :ế
Gi i thích khái ni m lu ng (streams) và t p tin (files)
Th o lu n các lu ng văn b n và các lu ng nh phân
Gi i thích các hàm x lý t p tin
Gi i thích con tr t p tin
Th o lu n con tr kích ho t hi n hành
Gi i thích các đ i s t dòng nh c l nh (command-line).
Gi i thi u
H u h t các ch ng trình đ u yêu c u đ c ghi d li u vào các h th ng l u tr trên đĩa. Các ế ươ ư
ch ng trình x văn b n c n l u các t p tin văn b n, ch ng trình x b ng tính c n l u n iươ ư ươ ư
dung c a các ô, ch ng trình c s d li u c n l u các m u tin. Bài này s khám phá các ti n ích ươ ơ ư
trong C dành cho các thao tác nh p/xu t (I/O) đĩa h th ng.
Ngôn ng C không ch a b t kỳ câu l nh nh p/xu t nào m t cách t ng minh. T t c các thao tác ườ
nh p/xu t đ u th c hi n thông qua các hàm th vi n chu n c a C. Ti p c n này làm cho h th ng ư ế
qu n t p tin c a C r t m nh uy n chuy n. Nh p/xu t trong C tuy t v i d li u th
truy n d ng nh phân hay d ng văn b n mà con ng i có th đ c đ c. Đi u này làm cho vi c ườ ượ
t o t p tin đ đáp ng m i nhu c u m t cách d dàng.
Vi c hi u s khác bi t gi a stream t p tin là r t quan tr ng. H th ng nh p/xu t c a C cung
c p cho ng i dùng m t giao di n đ c l p v i thi t b th t s đang truy c p. Giao di n này không ườ ế
ph i m t t p tin th t s m t s bi u di n tr u t ng c a thi t b . Giao di n tr u t ng ượ ế ượ
này đ c g i là m t stream và thi t b th t s đ c g i là ượ ế ượ t p tin.
21.1 File Streams
H th ng t p tin c a C làm vi c đ c v i r t nhi u thi t b khác nhau bao g m máy in, đĩa, ượ ế
băng t các thi t b đ u cu i. M c t t c các thi t b đ u khác nhau, nh ng h th ng t p tin ế ế ư
vùng đ m s chuy n m i thi t b v m t thi t b logic g i m t stream. m i ế ế streams ho t
đ ng t ng t , nên vi c qu n lý các thi t b là r t d dàng. Có hai lo i streams ươ ế văn b n (text)
nh phân (binary).
21.1.1 Streams văn b n
M t streams văn b n m t chu i các t . Các streams văn b n th đ c t ch c thành các ư
dòng, m i dòng k t thúc b ng m t t sang dòng m i. Tuy nhiên, t sang dòng m i tùy ế
ch n trong dòng cu i đ c quy t đ nh khi cài đ t. H u h t các trình biên d ch C không k t thúc ượ ế ế ế
stream văn b n v i t sang dòng m i. Trong m t stream văn b n, th x y ra m t vài s
chuy n đ i t khi môi tr ng yêu c u. Ch ng h n nh , t sang dòng m i th đ c ườ ư ượ
chuy n thành m t c p t v đ u dòng/nh y đ n dòng k . v y, m i quan h gi a các t ế ế
đ c ghi (hay đ c) nh ng t thi t b ngo i vi th không ph i m i quan h m t-m t.ượ ế
Và cũng vì s chuy n đ i có th x y ra này, s l ng ký t đ c ghi (hay đ c) có th không gi ng ượ ượ
nh s l ng ký t nhìn th y thi t b ngo i vi.ư ượ ế
Qu n lý t p tin 29
21.1.2 Streams nh phân
M t streams nh phân m t chu i các byte v i s t ng ng m t-m t v i thi t b ngo i vi, ươ ế
nghĩa là, không s chuy n đ i t . Cũng v y, s l ng byte đ c (hay ghi) cũng s gi ng ượ
nh s l ng byte thi t b ngo i vi. Các stream nh phân là các chu i byte thu n túy, mà không cóư ượ ế
b t kỳ ký hi u nào đ c dùng đ ch ra đi m k t thúc c a t p tin hay k t thúc c a record. K t thúc ượ ế ế ế
c a t p tin đ c xác đ nh b ng đ l n c a t p tin. ượ
21.2 Các hàm v t p tin và structure FILE
M t t p tin th tham chi u đ n b t c cái : t m t t p tin trên đĩa đ n m t thi t b đ u cu i ế ế ế ế
hay m t máy in. Tuy nhiên, t t c các t p tin đ u không cùng kh năng. d nh , m t t p tin ư
trên đĩa có th h tr truy c p ng u nhiên trong khi m t bàn phím thì không. M t t p tin s k t h p ế
v i m t stream b ng cách th c hi n thao tác m . T ng t , s thôi k t h p v i m t stream ươ ế
b ng thao tác đóng. Khi m t ch ng trình k t thúc bình th ng, t t c các t p tin đ u t đ ng ươ ế ườ
đóng. Tuy nhiên, khi m t ch ng trình b treo ho c k t thúc b t th ng, các t p tin v n còn m . ươ ế ườ
21.2.1 Các hàm c b n v t p tinơ
M t h th ng qu n t p tin theo chu n ANSI bao g m m t s hàm liên quan v i nhau. Các hàm
thông d ng nh t đ c li t kê trong b ng 21.1. ượ
Name Function
fopen() M m t t p tin
fclose() Đóng m t t p tin
fputc() Ghi m t ký t vào m t t p tin
fgetc() Đ c m t ký t t m t t p tin
fread() Đ c t m t t p tin vào m t vùng đ m
fwrite() Ghi t m t vùng đ m vào t p tin
fseek() Tìm m t v trí nào đó trong t p tin
fprintf() Ho t đ ng gi ng nh printf(), nh ng trên m t t p tin ư ư
fscanf() Ho t đ ng gi ng nh scanf(), nh ng trên m t t p tin ư ư
feof() Tr v true n u đã đ n cu i t p tin (end-of-file) ế ế
ferror() Tr v true n u x y ra m t l i ế
rewind() Đ t l i con tr đ nh v trí (position locator) bên trong t p tin v đ u t p
tin
remove() Xóa m t t p tin
fflush() Ghi d li u t m t vùng đ m bên trong vào m t t p tin xác đ nh
B ng 21.1: Các hàm c b n v t p tin ơ
Các hàm trên ch a trong t p tin header stdio.h. T p tin header này ph i đ c bao g m vào ch ng ượ ươ
trình s d ng các hàm này. H u h t các hàm này t ng t nh các hàm nh p/xu t t thi t b ế ươ ư ế
nh p xu t chu n. T p tin header stdio.h còn đ nh nghĩa m t s macro s d ng trong quá trình x
t p tin. d nh , macro EOF đ c đ nh nghĩa -1, ch a giá tr tr v khi m t hàm c đ c ti p ư ượ ế
khi đã đ n cu i t p tin.ế
21.2.2 Con tr t p tin
M t con tr t p tin (file pointer) r t c n thi t cho vi c đ c và ghi các t p tin. Nó là m t con tr đ n ế ế
m t structure ch a thông tin v t p tin. Thông tin bao g m: tên t p tin, v trí hi n t i c a t p tin,
t p tin đang đ c đ c hay ghi, b t kỳ l i nào xu t hi n hay đã đ n cu i t p tin. Ng i dùng ượ ế ườ
30 L p trình c b n C ơ
không c n thi t ph i bi t chi ti t, vì các đ nh nghĩa l y t studio.h bao g m m t khai báo ế ế ế
structure tên là FILE. Câu l nh khai báo duy nh t c n thi t cho m t con tr t p tin là: ế
FILE *fp;
Khai báo này cho bi t ếfp là m t con tr tr đ n m t FILE. ế
21.3 Các t p tin văn b n
nhi u hàm khác nhau đ qu n t p tin văn b n. Chúng ta s th o lu n trong các đo n bên
d i:ướ
21.3.1 M m t t p tin văn b n
Hàm fopen() m m t stream đ s d ngliên k t m t t p tin v i stream đó. Con tr k t h p v i ế ế
t p tin đ c tr v t hàm ượ fopen(). Trong h u h t các tr ng h p, t p tin đang m m t t p tin ế ườ
trên đĩa. Nguyên m u c a hàm fopen() là:
FILE *fopen(const char *filename, const char *mode);
trong đó filename m t con tr tr đ n chu i t ch a m t tên t p tin h p l cũng th ế
ch a c ph n t đ ng d n. Chu i đ c tr đ n b i con tr ườ ượ ế mode xác đ nh cách th c t p tin
đ c m . B ng 21.2 li t kê các ch đ h p l mà m t t p tin có th m . ượ ế
Chế
đÝ nghĩa
r M m t t p tin văn b n đ đ c
w T o m t t p tin văn b n đ ghi
a N i vào m t t p tin văn b n
r+ M m t t p tin văn b n đ đ c/ghi
w+ T o m t t p tin văn b n đ đ c/ghi
a+f N i ho c t o m t t p tin văn b n đ đ c/
ghi
B ng 21.2: Các ch đ m t p tin văn b n. ế
B ng 21.2 cho th y các t p tin th đ c m nhi u ch đ khác nhau. M t con tr null đ c ượ ế ượ
tr v n u x y ra l i khi hàm fopen() m t p tin. L u ý r ng các chu i nh “a+f” có th đ c bi u ế ư ư ượ
di n nh “af+”. ư
N u ph i m m t t p tin ế xyz đ ghi, câu l nh s là:
FILE *fp;
fp = fopen ("xyz", "w");
Tuy nhiên, m t t p tin nói chung đ c m b ng cách s d ng m t t p h p các câu l nh t ng t ượ ươ
nh sau:ư
FILE *fp;
if ((fp = fopen ("xyz", "w")) == NULL)
{
printf("Cannot open file");
exit (1);
}
Qu n lý t p tin 31
Macro NULL đ c đ nh nghĩa trong stdio.h ượ \0’. N u s d ng ph ng pháp trên đ m m t t pế ươ
tin, thì hàm fopen() s phát hi n ra l i n u có, ch ng h n nh đĩa đang ch đ c m ghi (write- ế ư ế
protected) hay đĩa đ y, tr c khi b t đ u ghi đĩa. ướ
N u m t t p tin đ c m đ ghi, b t kỳ m t t p tin nào cùng tên đang m s b vi t ch ngế ượ ế
lên. Vì khi m t t p tin đ c m ch đ ghi, thì m t t p tin m i đ c t o ra. N u mu n n i thêm ượ ế ư ế
các m u tin vào t p tin đã có, thì nó ph i đ c m v i ch đ “a”. N u m t t p tin đ c m ch ượ ế ế ượ ế
đ đ c không t n t i, hàm s tr v l i. N u m t t p tin đ c m đ đ c/ghi, s không ế ượ
b xóa n u đã t n t i. Tuy nhiên, n u nó không t n t i, thì nó s đ c t o ra. ế ế ượ
Theo chu n ANSI, tám t p tin th đ c m t i m t th i đi m. Tuy v y, h u h t các trình biên ượ ế
d ch C và môi tr ng đ u cho phép m nhi u h n tám t p tin. ườ ơ
21.3.2 Đóng m t t p tin văn b n
s l ng t p tin th m t i m t th i đi m b gi i h n, vi c đóng m t t p tin khi không còn ượ
s d ng m t đi u quan tr ng. Thao tác này s gi i phóng tài nguyên làm gi m nguy c v t ơ ượ
quá gi i h n đã đ nh. Đóng m t stream cũng s làm s ch và chép vùng đ m k t h p c a nó ra ngoài ế
(m t thao tác quan tr ng đ tránh m t d li u) khi ghi ra đĩa. Hàm fclose() đóng m t stream đã
đ c m b ng hàm ượ fopen(). Nó ghi b t kỳ d li u nào còn l i trong vùng đ m c a đĩa vào t p tin.
Nguyên m u c a hàm fclose() là:
int fclose(FILE *fp);
trong đó fp m t con tr t p tin. Hàm fclose() tr v 0 n u đóng thành công. B t kỳ giá tr tr vế
nào khác 0 đ u cho th y l i x y ra. Hàm fclose() s th t b i n u đĩa đã s m đ c g ra kh i ế ượ
đĩa ho c đĩa b đ y.
M t hàm khác dùng đ đóng stream hàm fcloseall(). Hàm này h u d ng khi ph i đóng cùng m t
lúc nhi u stream đang m . Nó s đóng t t c các stream và tr v s stream đã đóng ho c EOF n u ế
có phát hi n l i. Nó có th đ c s d ng theo cách nh sau: ượ ư
fcl = fcloseall();
if (fcl == EOF)
printf("Error closing files");
else
printf("%d file(s) closed", fcl);
21.3.3 Ghi m t ký t
Streams th đ c ghi vào t p tin theo t ng t m t ho c theo t ng chu i. Tr c h t chúng ta ượ ướ ế
hãy th o lu n v cách ghi các t vào t p tin. Hàm fputc() đ c s d ng đ ghi các t vàoượ
t p tin đã đ c m tr c đó b ng hàm ượ ướ fopen(). Nguyên m u c a hàm này nh sau: ư
int fputc(int ch, FILE *fp);
trong đó fp m t con tr t p tin tr v b i m fopen() ch t c n ghi. M c ch đ cượ
khai báo ki u int, nh ng đ c hàm ư ượ fputc() chuy n đ i thành ki u unsigned char. Hàm
fputc() ghi m t t o stream đã đ nh t i v trí hi n hành c a con tr đ nh v trín trong t p tin
sau đó tăng con tr này lên. N u ế fputc() thành công, tr v t đã ghi, ng c l i tr v ượ
EOF.
21.3.4 Đ c m t ký t
Hàm fgetc() đ c dùng đ đ c các t t m t t p tin đã đ c m ch đ đ c, s d ng hàmượ ượ ế
fopen(). Nguyên m u c a hàm là:
32 L p trình c b n C ơ
int fgetc (FILE *fp);
trong đó fp m t con tr t p tin ki u FILE tr v b i hàm fopen(). Hàm fgetc() tr v t k ế
ti p c a v trí hi n hành trong stream input, tăng con tr đ nh v trí bên trong t p tin lên. tế
đ c đ c m t t ki u ượ unsigned char đ c chuy n thành ki u ượ int. N u đã đ n cu i t pế ế
tin, fgetc() tr v EOF.
Đ đ c m t t p tin văn b n t đ u cho đ n cu i, câu l nh s là: ế
do
{
ch = fgetc(fp);
} while (ch != EOF);
Ch ng trình sau đây nh n các ký t t bàn phím và ghi chúng vào m t t p tin cho đ n khi ng iươ ế ườ
dùng nh p ký t @’. Sau khi ng i dùng nh p thông tin vào, ch ng trình s hi n th n i dung raườ ươ
màn hình.
Ví d 1:
#include <stdio.h>
main()
{
FILE *fp;
char ch= ' ';
/* Writing to file JAK */
if ((fp=fopen("jak", "w"))==NULL)
{
printf("Cannot open file \n\n");
exit(1);
}
clrscr();
printf("Enter characters (type @ to terminate): \n");
ch = getche();
while (ch !='@')
{
fputc(ch, fp) ;
ch = getche();
}
fclose(fp);
/* Reading from file JAK */
printf("\n\nDisplaying contents of file JAK\n\n");
if((fp=fopen("jak", "r"))==NULL)
{
printf("Cannot open file\n\n");
exit(1);
}
do
{
ch = fgetc (fp);
putchar(ch) ;
} while (ch!=EOF);
Qu n lý t p tin 33