DỮ LIỆU DẠNG FILE

Chia sẻ: Nguyen Trong Thong | Ngày: | Loại File: DOC | Số trang:28

0
31
lượt xem
2
download

DỮ LIỆU DẠNG FILE

Mô tả tài liệu
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Có thể phân chia nhập/xuất tập tin của C/C++ thành 2 loại: nhập/xuất chuẩn (hay còn gọi là nhập/xuất dòng) và nhập/xuất hệ thống (hay nhập/xuất mức thấp). Mỗi loại là 1 hệ thống hoàn chỉnh để truy xuất đĩa.

Chủ đề:
Lưu

Nội dung Text: DỮ LIỆU DẠNG FILE

  1. DỮ LIỆU KIỂU FILE 1. CÁC KIỂU NHẬP XUẤT ĐĨA a. Nhập/xuất chuẩn với nhập/xuất hệ thống Có thể phân chia nhập/xuất tập tin của C/C++ thành 2 loại: nhập/xuất chuẩn (hay còn gọi là nhập/xuất dòng) và nhập/xuất hệ thống (hay nhập/xuất mức thấp). Mỗi loại là 1 hệ thống hoàn chỉnh để truy xuất đĩa.  Nhập/xuất hệ thống: thực hiện việc đọc/ghi như DOS. Không có dịch vụ nhập xuất riêng cho từng kiểu dữ liệu mà chỉ có dịch vụ đọc ghi một dãy các byte. Như vậy để ghi 1 số thực lên đĩa ta phải dùng dịch vụ ghi 4 byte, để ghi 4 số nguyên ta dùng dịch vụ ghi 8 byte. Mỗi tệp có 1 số hiệu (handle), làm việc với tệp thông qua số hiệu tệp.  Nhập/xuất chuẩn: thường được sử dụng hơn vì có nhiều lệnh và sử dụng dễ dàng - Có dịch vụ truy xuất cho từng kiểu dữ liệu, có hàm nhập xuất ký tự, chuỗi, số nguyên, số thực, cấu trúc.... - C/C++ tự động cung cấp một vùng đệm, mỗi lần đọc ghi thì thường tiến hành trên vùng đệm chứ không trên tệp (tức là ghi nào đầy vùng đệm mới được đẩy lên đĩa, đọc thông tin lấy trên vùng đệm khi nào vùng đệm trống mới lấy dữ liệu từ tệp lên vùng đệm). Việc sử dụng vùng đệm giảm số lần nhập xuất trên đĩa và nâng cao tốc độ làm việc.  Đối tệp của hàm là biến con trỏ tệp b. Nhập/xuất nhị phân và văn bản Lý do tồn tại 2 kiểu này là do trước đây hệ điều hành UNIX (giai đoạn đầu tiên của ngôn ngữ C) làm theo 1 cách còn hệ điều hành MS-DOS lại làm theo cách khác.  Kiểu nhị phân: - Bảo toàn dữ liệu: trong quá trình nhập xuất dữ liệu không bị biến đổi, dữ liệu ghi trên tệp theo các byte nhị phân như trong bộ nhớ. - Mã kết kết thúc tệp: trong khi đọc nếu gặp cuối tệp thì ta nhận được mã kết thúc tệp EOF (định nghĩa trong stdio.h là -1) và hàm feof cho giá trị khác không. Ta chọn số -1 làm mã kết htúc tệp bởi vì nếu chưa gặp cuối tệp thì sẽ đọc 1 byte có giá trị từ 0 đến 255. Như vậy giá trị -1 sẽ không trùng với bất kỳ byte nào đọc được từ tệp.  Kiểu văn bản: - kiểu nhập/xuất văn bản chỉ khác kiểu nhị phân khi xử lý ký tự chuyển dòng LF (Line Feed - mã 10) và ký tự mã 26. - Mã chuyển dòng: khi ghi 1 ký tự LF (mã 10) được chuyển thành 2 ký tự CR (carriage Return - mã 13) và LF. Khi đọc 2 ký tự liên tiếp CR và LF trên tệp chỉ cho 1 ký tự LF. Còn tệp nhị phân chỉ ghi lên tệp 1 ký tự mã 10. (để phù hợp với DOS kết thúc bởi 2 mã 13 và 10) - Mã kết thúc tệp: EOF (số -1) và hàm feof(fp) cho giá trị khác 0 (số 1) 2. NHẬP/XUẤT CHUẨN Các hàm sử dụng cấu trúc FILE và mã kết thúc EOF, tất cả đều được khai báo và định nghĩa trong tệp . Mã EOF bằng (-1) và cấu trúc FILE gồm các thành phần dùng để quản lý tập tin: - level : cho biết có còn dữ liệu trong vùng đệm không - bsize: độ lớn vùng đệm (mặc định 512 byte) - flags : các cờ trạng thái file như tệp chỉ đọc, tệp nhị phân,... a. Đóng mở tệp  Hàm fopen: mở tệp FILE *fopen(const char *tên_tệp, const char *kiểu); Trịnh Vân Anh 86
  2. Hàm dùng để mở tệp, nếu thành công hàm cho con trỏ kiểu FILE ứng với tệp vừa mở, nếu có lỗi hàm cho giá trị kiểu NULL. Đối thứ nhất của fopen là tên của tệp, có dạng một xâu kí tự. Đối thứ hai là mode, cũng là xâu kí tự chỉ ra cách ta định sử dụng tệp. Các mode sử dụng trong khi mở tệp là: MODE Ý NGHĨA Mở file đã tồn tại để đọc theo kiểu văn bản (read only), nếu không tồn tại có lỗi “r” “rt” Mở file mới để ghi theo kiểu văn bản. Nếu file đã tồn tại, nội dung của nó sẽ bị “w” “wt” loại bỏ để thay vào đó nội dung mới Mở 1 tệp để ghi bổ sung theo kiểu văn bản, nếu tệp chưa tồn tại thì tạo tệp mới “a” “at” “r+” “r+t” Mở 1 tệp để đọc/ghi theo kiểu văn bản, nếu không tồn tại sẽ báo lỗi Mở file mới để đọc/ghi theo kiểu văn bản. Nếu file đang tồn tại nội dung của nó “w+” sẽ bị huỷ để thay vào nội dung mới “w+t” Mở file để đọc/ghi bổ xung theo kiểu văn bản, nếu tệp chưa tồn tại thì tạo mới “a+” “a+t” Mở file để đọc theo kiểu nhị phân, nếu tệp không tồn tại sẽ có lỗi Mở file mới để ghi theo kiểu nhị phân. Nếu file đang tồn tại, nội dung của file bị “rb” xoá bỏ để ghi vào thông tin mới “wb” Mở file nhị phân đang tồn tại để ghi thêm dữ liệu vào cuối file. Nếu file chưa tồn tại, một file mới sẽ được tạo ra “ab” Mở file nhị phân mới cho đọc/ghi. Nếu file không tồn tại thì báo lỗi mở 1 tệp mới để đọc/ghi theo kiểu nhị phân, nếu tệp đã tồn tại thì bị xoá “r + b” Mở file nhị phân đang tồn tại và ghi thêm dữ liệu vào cuối file. Nếu file chưa tồn “w+b” tại thì một file mới sẽ được tạo ra “a + b” Chú ý: Trong các kiểu đọc/ghi, cần làm sạch vùng đệm trước khi chuyển từ đọc sang ghi hoặc từ ghi sang đọc. Có thể tên tệp có định đường dẫn, “w” chuỗi chứ không phải là ký tự. Ví dụ: FILE *fp; fp=fopen(“tep_mo.txt”,”w”); Hàm fclose: đóng tệp int fclose(FILE *fp); Hàm dùng để đóng tệp,fd là con trỏ tương ứng với tệp cần đóng. Nội dung đóng tệp:Đẩy dữ liệu còn trong vùng đệm lên đĩa (khi đang ghi),xoá vùng đệm (khi đang đọc) Giải phóng biến fp để dùng cho tệp khác. Nếu thành công hàm cho giá trị 0, ngược lại hàm cho EOF. Ví dụ: fclose(fp); Hàm fcloseall: đóng các tệp đang mở int fcloseall(void); Đóng tất cả tệp đang mở, thành công hàm cho giá trị nguyên bằng số tệp đóng được, trái lại hàm cho EOF Hàm fflush: làm sạch vùng đệm int fflush(FILE *fp); Hàm dùng làm sạch vùng đệm của tệp fp, nếu thành công hàm cho giá trị 0, ngược lại hàm cho EOF Hàm fflushall: làm sạch vùng đệm int fflushall(void); Hàm dùng làm sạch vùng đệm của các tệp đang mở, nếu thành công hàm cho giá trị nguyên bằng Trịnh Vân Anh 87
  3. số tệp đang mở, ngược lại hàm cho EOF. Hàm ferror: kiểm tra lỗi int ferror(FILE *fp); Hàm kiểm tra lỗi thao tác trên tệp fp, Hàm cho giá trị 0 nếu không lỗi, ngược lại hàm cho giá trị khác 0.  Hàm perror: thông báo lỗi hệ thống void perror(const char *s); Hàm đưa ra chuỗi s và thông báo lỗi. Ví dụ: lỗi vào ra #include #include void main(void) { FILE *fp; char name[30]; if(fp=fopen(“ten_tep.txt”,”w”)==NULL) { printf(“\n khong the mo duoc tep ten_tep.txt”); exit();} do { fprintf(fp,”%s”,name); if(ferror(fp)) { perror(“loi ghi tep:”); fclose(fp); exit(); } } while (strlen(name)>1); fclose(fp); } Kết quả in ra dòng thông báo: Loi ghi tep: Bad data  Hàm feof: Kiểm tra cuối tệp int feof(FILE *fp); Dùng để kiểm tra cuối tệp, hàm cho giá trị khác không gặp cuối tệp khi đọc, ngược lại cho giá trị 0  Hàm unlink: xoá tệp int unlink(const char *ten_tep); Hàm dùng để xoá tệp tin trên đĩa, nếu thành công hàm cho giá trị = 0, ngược lại cho EOF b. Nhập/xuất ký tự Các hàm putc và fputc int putc(int ch,FILE *fp); int fputc(int ch,FILE *fp); Ghi ký tự lên tệp, thành công cho mã ký tự được ghi, ngược lại cho EOF.Hai hàm có ý nghĩa như nhau. Ví dụ: ghi từng ký tự vào tập tin #include “stdio.h” void main(void) { FILE *fp; char ch; fp=fopen(“tep.txt”,”w”); while ((ch=getche()) != ‘\r’) Trịnh Vân Anh 88
  4. putc(ch,fp); fclose(fp); } Các hàm getc fgetc int getc(FILE *fp); int fgetc(FILE *fp); Hàm đọc 1 ký tự từ tệp fp, nếu thành công hàm cho mã đọc được (có giá trị t ừ 0 đ ến 255). Nếu gặp cuối tệp hay có lỗi hàm cho EOF. Chú ý: hai hàm trên có ý nghĩa như nhau, trong kiểu văn bản hàm đọc cả 2 mã 13,10 một lúc và trả về giá trị 10, khi gặp mã 26 thì không trả về 26 mà trả về EOF. Ví dụ 1: đọc mỗi lần 1 ký tự từ tập tin #include “stdio.h” void main(void) { FILE *fp; int ch; fp=fopen(“tep.txt”,”r”); while ((ch=getc(fp)) != EOF) printf(“%c”,ch); fclose(fp); } ví dụ 2: Sao chép tệp nhị phân #include “stdio.h” void main(void) { FILE f1,f2; char tep1[12],tep2[12]; int ch; printf(“\n tep nguon:”); gets(tep1); printf(“\n tep dich:”); gets(tep2); f1=fopen(tep1,”rb”); if (f1==NULL) { printf(“\n tep %s chua co”,tep1); getch(); return; } f2=fopen(tep2,”wb”); while ((ch=fgetc(f1)) != EOF) fputc(ch,f2); fclose(f1); fclose(f2); } c. Các hàm nhập/xuất theo kiểu văn bản Hàm fprintf: ghi dữ liệu theo khuôn dạng int fprintf(FILE *fp, const char *dk,....); Giá trị các đối được ghi lên tệp fp theo khuôn dạng xác định trong chuỗi điều khiển dk. Nếu thành công hàm trả về giá trị nguyên bằng số byte ghi lên tệp, khi có lỗi trả về EOF. Hàm làm việc giống như printf. Trịnh Vân Anh 89
  5. Ví dụ: đưa dữ liệu và tệp #include int main(void) { FILE *fp; int i = 100; char c = 'C'; float f = 1.234; /* open a file for update */ fp = fopen("dl.dat", "w+"); /* write some data to the file */ fprintf(fp, "%d %c %f", i, c, f); /* close the file */ fclose(fp); return 0; } Ví dụ : đưa dữ liệu nhập từ bàn phím vào tệp #include “stdio.h” void main(void) { FILE *fp; int i; fp=fopen(“tep.txt”,”wt”); fprintf(fp,”Hoc vien cong nghe BCVT 1”); for(i=1;i
  6. void main(void) { FILE *fp; int c; fp=fopen(“slieu.dat”,”r”); while(1) { fscanf(fp,”%d”,&c); if(feof(fp)) break; printf(“\n %d”,c); } fclose(fp); getch(); } Ví dụ: ma trận nghịch đảo Cho tệp : mtndao.dat có dạng: - Dòng đầu tiên là số tự nhiên n (cấp của ma trận vuông A) - n dòng tiếp theo mỗi dòng ghi n số thực phân biệt nhau bởi dấu cách là A[i][j] Hãy viết chương trình tính ma trận nghịch đảo của ma trận A và viết tiếp vào file trên. #include #include #include FILE *f; int Chuyen(float **, int ,int); void Mtdao(float **,int ); int Chuyen(float **A, int n,int i) { int j,k; float t; for(j=i+1;j
  7. return; } } for(j=i+1;j
  8. for(i=0;i
  9. { FILE *fp; int i=0; char d[256]; fp=fopen(“xau.dat”,”r”); clrscr(); while(!feof(fp)) { ++i; fgets(d,256,fp); printf(“\n Lop D99 VT %d : %s”,fp,d);); } fclose(fp); getch(); } Ví dụ: #include #include int main(void) { FILE *fp; char string[] = "This is a test"; char msg[20]; /* open a file for update */ fp = fopen("dl.dat", "w+"); /* write a string into the file */ fwrite(string, strlen(string), 1, stream); /* seek to the start of the file */ fseek(stream, 0, SEEK_SET); /* read a string from the file */ fgets(msg, strlen(string)+1, stream); /* display the string */ printf("%s", msg); fclose(stream); return 0; } Tệp văn bản và các thiết bị chuẩn Ngôn ngữ C định nghĩa các tệp và con trỏ tệp ứng với các thiết bị chuẩn: Tệp con trỏ thiết bị thiết bị vào chuẩn (bàn phím) in stdin thiết bị ra chuẩn (màn hình) out stdout thiết bị lỗi chuẩn (màn hình) err stderr thiết bị in chuẩn (máy in) prn stdprn Khi chương trình C bắt đầu làm việc thì các tệp này tự động mở, vì vậy có thể dùng các con trỏ trên để nhập/xuất trên các thiết bị chuẩn. Ví dụ: #include “stdio.h” #include “conio.h” Trịnh Vân Anh 94
  10. void main(void) { char hten[20]; float diem; int nsinh; printf(“\n ho va ten: “);fgets(hten,20,stdin); printf(“\n diem: “); fsanf(stdin,”%f”,&diem); printf(“\n nam sinh :”);fscanf(stdin,”%d”&nsinh); fputs(hten,stderr); fprintf(stdout,”Diem %f nam sinh:%d”,diem,nsinh); fclose(fp); getch(); } d. Các hàm nhập/xuất theo kiểu nhị phân Hàm putw: ghi 1 số nguyên int putw(int n, FILE *fp); Ghi gía trị n lên tệp fp dạng 2byte, thành công hàm trả về số nguyên được ghi, có lỗi trả về EOF. Hàm getw: đọc 1 số nguyên int getw(FILE *fp); Đọc 1 số nguyên (2byte) từ tệp fp, thành công hàm trả về số nguyên đọc được, có lỗi trả về EOF. Ví dụ: ghi và đọc số nguyên #include “stdio.h” #include “conio.h” void main(void) { FILE *fp; int i; fp=fopen(“nguyen.dat”,”wb”); for(i=100;i
  11. fp = fopen(FNAME, "wb"); if (fp == NULL) { printf("Error opening file %s\n", FNAME); exit(1); } word = 94; putw(word,fp); if (ferror(fp)) printf("Error writing to file\n"); else printf("Successful write\n"); fclose(fp); /* reopen the file */ fp = fopen(FNAME, "rb"); if (fp == NULL) { printf("Error opening file %s\n", FNAME); exit(1); } /* extract the word */ word = getw(fp); if (ferror(fp)) printf("Error reading file\n"); else printf("Successful read: word = %d\n", word); /* clean up */ fclose(fp); unlink(FNAME); return 0; } Hàm fwrite: ghi các số nguyên, số thực hay cấu trúc lên tệp int fwrite (void *ptr, int size, int n, FILE *fp); Ghi n phần tử trong đó kích cỡ của mỗi phần tử là size byte từ con trỏ ptr vào t ệp đ ược trỏ b ởi con trỏ file fp, hàm trả về giá trị là số phần tử được ghi. Hàm fread: đọc các số nguyên, số thực hay các cấu trúc từ tệp int fread (void *ptr, int size, int n, FILE *fp); Đọc vào con trỏ ptr n phần tử mỗi phần tử có kích cỡ n byte từ tệp được trỏ bởi con trỏ file fp, hàm trả lại số phần tử thực sự được đọc. Ví dụ: #include struct mystruct { int i; char ch; }; int main(void) { Trịnh Vân Anh 96
  12. FILE *fp; struct mystruct s; if ((fp = fopen("thu.txt", "wb")) == NULL) /* open file thu.txt */ { fprintf(stderr, "Cannot open output file.\n"); return 1; } s.i = 0; s.ch = 'A'; fwrite(&s, sizeof(s), 1, fp); /* write struct s to file */ fclose(fp); /* close file */ return 0; }  Hàm trả về số hiệu (handle) của file: int fileno(fd); Trả về số hiệu (handle) của file, mỗi file đều có số hiệu cho file đó.  Hàm trả về kích thước của file: long filelength(int handle); Hàm trả về kích thước tính bằng byte của file có số hiệu là handle. Ví dụ : cấu trúc ghi lên tệp #include #include #include #include // toupper() #include #include //filelength() #define ESC 27 typedef struct{ unsigned int ng; unsigned int th; unsigned int nam; }Date; typedef struct{ char masv[8]; char hten[30]; Date ns; float d1,d2,d3,dtb; char xloai[15]; } svien; void ghi(char *name) { svien s; FILE *f; char tl='C'; float t; clrscr(); f=fopen(name,"w"); if(f==NULL){ Trịnh Vân Anh 97
  13. printf("\n khong tao duoc tep"); return; } do{ printf("\n ma so sinh vien:"); fflush(stdin); gets(s.masv); printf("\n Ho va ten:"); fflush(stdin); gets(s.hten); printf("\n ngay :"); fflush(stdin); scanf("%d",&s.ns.ng); printf("\n thang :"); scanf("%d",&s.ns.th); printf("\n nam :"); scanf("%d",&s.ns.nam); printf("\n diem 1 :"); scanf("%f",&t); s.d1=t; printf("\n diem 2 :"); scanf("%f",&t); s.d2=t; printf("\n diem 3 :"); scanf("%f",&t); s.d3=t; s.dtb=(s.d1+s.d2+s.d3)/3; if(s.dtb
  14. } void hthi(svien *s,int n) { int i; printf("\n Danh sach sinh vien"); printf("\n================================================================ =============="); printf("\n|STT| Mso sv | Ho ten |ngay sinh |diem 1|diem 2|diem 3|diem tb| xep loai |"); printf("\n================================================================ =============="); for(i=0;i
  15. int n,i; char ma[15]; int chon; do { clrscr(); printf("\n 1. nhap danh sach vao tep"); printf("\n 2. sap xep danh sach"); printf("\n 3. Tim theo ma sinh vien"); printf("\n 4. Hien thi danh sach"); printf("\n ESC. Thoat"); printf("\n chon:"); chon=getche(); switch(chon) { case '1':ghi(name); break; case '2': doc(name,s,&n); printf("\n Chua sap xep"); hthi(s,n); sxep(s,n); printf("\n Da sap xep"); hthi(s,n); getch(); break; case '3': doc(name,s,&n); printf("\n nhap ma sinh vien can tim:"); fflush(stdin); gets(ma); i=tknhiphan(s,n,ma); if(i==-1) printf("\n khong co hoc sinh co ma :%s",ma); else { printf("\n sinh vien thu %d trong danh sach",i); printf("\n ho ten:%s",s[i].hten); printf("\n Diem trung binh:%6.1f",s[i].dtb); printf("\n Xeploai:%s",s[i].xloai); } getch(); break; case '4': doc(name,s,&n); hthi(s,n); getch(); break; } }while(chon != ESC); } Trịnh Vân Anh 100
  16. void main() { menu(); }  Hàm fseek:di chuyển con trỏ định vị int fseek(FILE *fp, long sb, int xp); Hàm di chuyển con trỏ định vị của tệp fp từ vị trí xác định bởi xp: - SEEK_SET hoặc 0 : xuất phát từ đầu tệp - SEEK_CUR hay 1: xuất phát từ vị trị hiện tại của con trỏ định vị - SEEK_END hoặc 2: xuất phát từ cuối tệp qua 1 số byte bằng giá trị tuyệt đối của sb, sẽ di chuyển về cuối tệp nếu sb dương và ngược lại. Khi thành công hàm trả về 0, khi có lỗi hàm trả về giá trị khác 0. Ví dụ: tính độ dài của tệp #include long filesize(FILE *fp); int main(void) { FILE *fp; fp = fopen("MYFILE.TXT", "w+"); fprintf(fp, "This is a test"); printf("Filesize of MYFILE.TXT is %ld bytes\n", filesize(fp)); return 0; } long filesize(FILE *fp) { long curpos, length; curpos = ftell(fp); fseek(fp, 0L, SEEK_END); length = ftell(fp); fseek(fp, curpos, SEEK_SET); return length; }  hàm rewind: chuyển con trỏ về vị trí đầu tệp void rewind(FILE *fp); Chuyển con trỏ định vị của tệp fp về đầu tệp.  Hàm ftell: cho biết vị trí hiện tại của con trỏ định vị long ftell(FILE *fp); Thành công hàm cho biết vị trí hiện tại của con trỏ định vị (byte thứ mấy trên tệp fp). Số th ứ tự của byte được tính từ 0, có lỗi hàm trả về -1L. Ví dụ: #include int main(void) { FILE *f; f = fopen("thu.TXT", "w+"); fprintf(fp, "Chuong trinh vi du:"); Trịnh Vân Anh 101
  17. printf("Con tro dinh vi o %ld byte\n", ftell(fp)); return 0; } 3. NHẬP/XUẤT HỆ THỐNG Vào ra ở mức hệ thống hay còn gọi là mức thấp, đó là cách vào ra gần giống với MS-DOS đã dùng để đọc ghi trên các tệp. Trog vào ra ở mức hệ thống, dữ liệu không được ghi theo từng ký tự, từng chuỗi, hoặc theo các kiểu dữ liệu định trước như trong các kiểu vào ra chuẩn mà ghi theo bộ đệm. Trong cách thức vào ra chuẩn, kiểu dữ liệu sẽ qui định số byte cần đọc hay ghi, còn trong cach svào ra hệ thống, lập trình viên phải khởi tạo bộ đệm dữ liệu rồi đặt dữ liệu thích hợp vào đó trước khi ghi hoặc dùng chúng. Để sử dụng các hàm vào ra hệ thống ta cần tới các tệp tiêu đề sau: - io.h : chứa các nguyên mẫu của các hàm hệ thống - fcntl.h : chứa định nghĩa quyền truy nhập (access) - sys/stat.h : chứa định nghĩa thuộc tính (amode) - dos.h: chứa định nghĩa thuộc tính (attribute) theo DOS Ngoài ra còn cần đến biến chuẩn của Turbo C _fmode để xác định kiểu nhập/xuất nhị phân hay văn bản. Để duy trì tính kế thừa và khả năng tương thích của các chương trình viết bằng C trong hệ UNIX, các đối trong các hàm open, creat, chmod có liên quan đến UNIX. Để tiện dùng trong DOS TURBO C cũng đưa ra 1 số hàm tương tự như _open, _creat, _chmod,... sự khác nhau của chúng như sau: Kiểu truy nhập mặc định của creat và open là văn bản, còn của _creat, _open là nhị phân. Thuộc tính tệp trong các hàm creat và chmod là các hằng có đ ặc trưng UNIX định nghĩa trong . Thuộc tính tệp trong các hàm _creat và _chmod là các hằng định nghĩa trong . a. Tạo tệp, đóng mở tệp  Hàm creat: tạo tệp mới int creat(const char *fname, int amode); Tạo tệp mới có tên là fname, thuộc tính cho bởi amode (định nghĩa trong sys/stat.h): - S_IREAD: tệp chỉ đọc (không xoá, sửa, bổ sung) - S_IWRITE: tệp để ghi (có thể xoá, sửa, bổ sung) Trong trường hợp tệp đã tồn tại: nếu tệp để ghi thì nó bị xoá, nếu tệp chỉ đọc thì bị lỗi (hàm trả về -1) Khi thành công hàm trả về số hiệu tệp (handle) số hiệu này có thể dùng trong hàm write đ ể ghi thông tin lên tệp (ngay cả khi là tệp chỉ đọc). Kiểu ghi được xác định bởi biến fmode (mặc định là O_TEXT - kiểu văn bản), muốn ghi theo kiểu nhị phân thì ta xác định lại _fmode (trước hàm creat) : fmode=OBINARY. Ví dụ: tạo tệp chứa 7 số nguyên #include “io.h” #include “fcntl.h” #include “sys/stat.h” int a[7] = {1,2,3,4,5,6,7}; void main(void) { int fd; fmode=O_BINARY; Trịnh Vân Anh 102
  18. fd=creat(“nguyen.dat”,S_IWRITE); write(fd,a,14); close(fd); } Hàm _creat: tạo tệp mới int _creat(const char *fname,int attrib); Tạo tệp mới có tên là fname, thuộc tính cho bởi attrib (định nghĩa trong dos.h): - FA_RDONLY: tệp chỉ đọc (không xoá, sửa, bổ sung) - FA_ARCH: tệp để ghi (có thể xoá, sửa, bổ sung) - FA_HIDDEN: tệp ẩn giá trị của attrib có thể là tổ hợp của các giá trị trên: attrib=FA_HIDDEN|FA_RDONLY Trong trường hợp tệp đã tồn tại: nếu tệp để ghi thì nó bị xoá, nếu tệp chỉ đọc thì bị lỗi (hàm trả về -1) Khi thành công hàm trả về số hiệu tệp (handle) số hiệu này có thể dùng trong hàm write đ ể ghi thông tin lên tệp (ngay cả khi là tệp chỉ đọc). Kiểu ghi luôn luôn là nhị phân. Ví dụ: tạo tệp chứa 10 số nguyên #include “io.h” #include “dos.h” int a[10] = {1,2,3,4,5,6,7,8,9,10}; void main(void) { int fd; fd=_creat(“nguyen.dat”,FA_ARCH); write(fd,a,20); close(fd); } Hàm open: mở tệp (đã có) hoặc tạo tệp mới để ghi đọc int open(const char *fname,int access, [unsigned amode]); Mở tệp có tên là fname, access quyền và kiểu truy nhập: GIÁ TRỊ Ý NGHĨA ghi bổ sung O_APPEND nếu tệp tin chưa có thì nó được tạo (thêm đối O_CREAT thứ 3) O_RDONLY mở tệp để đọc O_RDWR đọc/ghi O_TRUNC xoá tệp nếu tồn tại (giữ nguyên thuộc tính) O_BINARY kiểu nhập/xuất nhị phân O_TEXT kiểu nhập/xuất văn bản - Có thể là tổ hợp của các giá trị trên (dùng phép |) - Nếu không mô tả rõ O_TEXT hay O_BINARY thì kiểu truy nhập được xác định bởi _fmode - Không có O_CREAT mở 1 tệp đã tồn tại lỗi xảy ra khi: tệp không tồn tại hoặc mở để ghi 1 tệp chỉ đọc - Có O_CREAT nếu tệp chưa có thì được tạo ra, lỗi xảy ra khi:mở để ghi 1 tệp chỉ đọc Khi thành công hàm trả về số hiệu tệp (dùng trong các hàm truy nhập tới tệp), có lỗi sẽ trả về -1 Ví dụ: Mở tệp tep.dat để ghi theo kiểu nhị phân, nếu đã tồn tại thì bị xoá, nếu chưa có thì được tạo ra: Trịnh Vân Anh 103
  19. int fd; fd=open(“tep.dat”,O_RDWR|O_BINARY|O_TRUNC|O_CREAT,S_IWRITE); Mở tệp tep1.dat (đã có) để đọc theo kiểu văn bản: fd=open(“tep1.dat”,O_RDONLY|O_TEXT); Hàm _open: mở tệp (đã tồn tại) để đọc ghi int _open(const char *fname,int oflag); Mở tệp có tên là fname, oflag quyền và kiểu truy nhập có ý nghĩa như đối với access trong hàm open, có khác là kiểu mặc định là O_TEXT và O_CREAT không tạo tệp mới. Mở 1 tệp đã tồn tại để truy nhập theo cách xác định bởi oflag, lỗi: tệp không tồn tại và mở để ghi 1 tệp chỉ đọc. Khi thành công hàm trả về số hiệu tệp (dùng trong các hàm truy nhập tới tệp), có lỗi sẽ trả về -1 Ví dụ: Mở và xoá tệp tep.dat (đã có) để ghi lại từ đầu theo kiểu văn bản: int fd; fd=_open(“tep.dat”,O_RDWR| O_TRUNC); Mở tệp tep1.dat (đã có) để đọc theo kiểu văn bản: fd=open(“tep1.dat”,O_RDONLY); Hàm close và _close: đóng tệp int close(int fd); int _close(int fd); Đóng tệp có số hiệu fd, và số hiệu đó có thể dùng để mở tệp khác. Thành công hàm trả về 0, lỗi trả -1 Hàm chmode: thay đổi thuộc tính của tệp int chmod(const char *fname,int amode); Đổi thuộc tính tệp fname theo amode: - S_IREAD: tệp chỉ đọc (không xoá, sửa, bổ sung) - S_IWRITE: tệp để ghi (có thể xoá, sửa, bổ sung) Hàm cho giá trị 0 nếu thành công còn -1 nếu lỗi Hàm _chmode: nhận hay thay đổi thuộc tính của tệp theo kiểu DOS int _chmod(const char *fname,int func,int attrib); Đổi thuộc tính tệp fname - Nếu func=0 hàm cho biết thuộc tính của tệp, không cần đối thứ 3 - Nếu func=1 thay đổi thuộc tính của tệp và cần đối thứ 3 Các giá trị của attrib: - FA_RDONLY: tệp chỉ đọc (không xoá, sửa, bổ sung) - FA_ARCH: tệp để ghi (có thể xoá, sửa, bổ sung) - FA_HIDDEN: tệp ẩn Cho biết thuộc tính của tệp fname (func=0), hoặc đổi thuộc tính của tệp (func=1) Hàm cho giá trị =0 nếu thành công, là -1 nếu lỗi Ví dụ: trả lại thuộc tính của tệp #include #include #include int get_file_attrib(char *filename); int main(void) { char filename[128]; int attrib; Trịnh Vân Anh 104
  20. printf("Enter a filename:"); scanf("%s", filename); attrib = get_file_attrib(filename); if (attrib & FA_RDONLY) printf("%s is read-only.\n", filename); if (attrib & FA_HIDDEN) printf("%s is hidden.\n", filename); if (attrib & FA_SYSTEM) printf("%s is a system file.\n", filename); if (attrib & FA_LABEL) printf("%s is a volume label.\n", filename); if (attrib & FA_ARCH) printf("%s is an archive file.\n", filename); } return 0; } /* returns the attributes of a DOS file */ int get_file_attrib(char *filename) { return(_chmod(filename, 0)); } b. Các hàm nhập/xuất dữ liệu trên tệp hệ thống Mặc định các hàm này dùng kiểu nhập xuất nhị phân Hàm write: ghi 1 dãy các byte lên tệp unsigned write(int fd, void *pt, unsigned n); Ghi n byte từ vùng nhớ chứa dữ liệu trỏ bởi con trỏpt lên tệp có số hiệu là fd. Khi thành công hàm trả về 1 số bằng số byte ghi được, khi có lỗi hàm trả về -1 (giá trị mà hàm trả về khác n). Ví dụ: tạo 1 tệp sau đó viết 1 chuỗi vào, nếu tệp đã có thì ghi đè #include #include #include #include #include #include int main(void) { int handle; char string[40]; int length, res; /* Create a file named "TEST.txt" in the current directory and write a string to it. If "TEST.txt" already exists, it will be overwritten. */ if ((handle = open("TEST.txt", O_WRONLY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE)) == -1) { printf("Error opening file.\n"); Trịnh Vân Anh 105
Đồng bộ tài khoản