Chương 4

TẬP TIN (File)

Nội dung trình bày

1. Giới thiệu tập tin 2. Các bước xử lý tập tin 3. Đọc – Ghi tập tin văn bản (Text file) 4. Đọc – Ghi tập tin nhị phân (Binary file)

2

1. Giới thiệu tập tin

 Tập tin là một tập hợp thông tin được đặt tên và lưu trữ ngoài của

được chứa trong các thiết bị máy tính như: đĩa cứng, đĩa mềm, CD, DVD,…

 Một tập tin luôn luôn kết thúc bằng 1 ký tự đặc

biệt ký hiệu là EOF (EndOfFile)

 Tập tin gắn liền với bộ nhớ đệm (buffer) trong đó các thông tin dữ liệu được lưu trữ tạm thời trước khi có sự trung chuyển giữa bộ nhớ máy tính và tập tin

3

1. Giới thiệu tập tin

 Để tạo kết nối với một tập tin, dùng lệnh fopen

◦ Khi tập tin được mở, thông tin có thể được trao đổi

 Để ngắt kết nối với một tập tin, dùng lệnh fclose

◦ Nếu đóng một tập tin đang mở thì nội dung của

giữa tập tin đó với chương trình

vùng đệm tương ứng được ghi ra thiết bị ngoài

◦ Quá trình này được gọi là flushing và đảm bảo là

4

không có thông tin bị để lại trong vùng đệm

1. Giới thiệu tập tin: Minh họa

a a

a

b

c

c c

Vùng đệm (buffer)

Tập tin

Dữ liệu đang xử lý

5

fclose

1. Giới thiệu tập tin

 Có 2 loại tập tin: ◦ Tập tin văn bản ◦ Tập tin nhị phân

Tập tin văn bản Tập tin nhị phân

Là tập tin mà các phần tử của nó là các ký tự

Mỗi lần đọc hay ghi là đọc hay ghi một ký tự

Là tập tin mà các phần tử là các số nhị phân biểu diễn thông tin

Việc đọc hay ghi tuỳ thuộc vào người lập trình

6

Khi xử lý ký tự chuyển dòng LF được chuyển thành 2 ký tự CR và LF

Nội dung trình bày

1. Giới thiệu tập tin 2. Các bước xử lý tập tin 3. Đọc – Ghi tập tin văn bản (Text file) 4. Đọc – Ghi tập tin nhị phân (Binary file)

7

Các bước xử lý tập tin

 Có 4 bước cơ bản để xử lý tập tin

1. Khai báo biến tập tin 2. Mở tập tin để ghi hoặc đọc 3. Ghi hoặc đọc tập tin (xử lý dữ liệu) 4. Đóng tập tin

8

Các bước xử lý tập tin: Bước 1

 Có 4 bước cơ bản để xử lý tập tin

1. Khai báo biến tập tin: ◦ Ví dụ:

FILE *Tên_con_trỏ;

9

FILE *fp;

Các bước xử lý tập tin: Bước 2

 Có 4 bước cơ bản để xử lý tập tin

2. Mở tập tin: fopen

FILE* fopen( const char* filename, const char* mode );

 filename: chứa đường dẫn và tên của tập tin cần mở  mode: cho biết mở tập tin theo kiểu nào

 r (đọc)  w (ghi)  a (ghi tiếp vào cuối tập tin)  r+ (đọc và ghi)  w+ (đọc và ghi, nhưng ghi đè lên nội dung cũ của tập tin)  a+ (đọc và ghi vào cuối tập tin)  rb, wb, ab, rb+, r+b, wb+, w+b, ab+, a+b giống như các

trường hợp trên nhưng chỉ dùng cho tập tin nhị phân

10

Các bước xử lý tập tin: Ví dụ

 Ví dụ: Mở tập tin

FILE *fp; fp = fopen("d:\\test.txt","w"); if (fp == NULL) {

cout << "Cannot open file"; exit(1);

11

}

Các bước xử lý tập tin: Bước 3

 Có 4 bước cơ bản để xử lý tập tin

 Mỗi kiểu tập tin có cách đọc và ghi khác nhau

3. Đọc hoặc ghi tập tin

 Khi đọc dữ liệu từ 1 tập tin, phải kiểm tra xem có phải là cuối tập tin hay chưa, vì đến cuối tập tin thì không thể đọc được nữa

 Để kiểm tra có phải cuối tập tin hay chưa, có thể dùng hàm feof hoặc dùng kết quả của những hàm đọc tập tin

int feof(FILE *fp);

12

◦ Chú ý:

Các bước xử lý tập tin: Bước 4

 Có 4 bước cơ bản để xử lý tập tin

4. Đóng tập tin:

int fclose( FILE *fp );

 fp: là con trỏ tập tin muốn đóng

◦ Khi hàm được gọi, nó sẽ viết bất kỳ dữ liệu nào vẫn

13

còn trong vùng đệm đến tập tin rồi đóng tập tin

Các bước xử lý tập tin

 Như vậy một chương trình xử lý tập tin có dạng

chung như sau: #include #include void main(){ FILE *fp; fp = fopen("thidu.dat","w"); if (fp==NULL) {

cout<<"Khong mo duoc tap tin"; exit(0);

} /* xử lý tập tin */ fclose(fp);

}

14

Nội dung trình bày

1. Giới thiệu tập tin 2. Các bước xử lý tập tin 3. Đọc – Ghi tập tin văn bản (Text file) 4. Đọc – Ghi tập tin nhị phân (Binary file)

15

Ghi tập tin văn bản: putc - fputc

 Có hai hàm ghi ký tự vào tập tin là putc và fputc. Hai hàm này là tương đương nhau

int putc( int ch, FILE *fp );

int fputc( int ch, FILE *fp );

◦ ch: kí tự muốn ghi vào tập tin ◦ fp: con trỏ tập tin

16

◦ Mỗi lần chỉ ghi được một kí tự vào tập tin

Ví dụ: putc - fputc

 Đọc ký tự từ bàn phím và ghi vào file đến khi gặp

kí tự $ void main() {

FILE *fp; char ch; if ( (fp=fopen(“test.txt”, "w")) == NULL ) { cout << "Cannot open file.\n";

exit(1);

} do {

//đọc từ bàn phím

//ghi vào file

ch = getchar(); fputc(ch, fp); }while (ch != '$');

fclose(fp);

//đóng file

}

17

Đọc tập tin văn bản: getc - fgetc

 Hàm đọc: getc hoặc fgetc

int getc( FILE *fp );

int fgetc( FILE *fp );

◦ fp: con trỏ tập tin

EOF nếu đọc được kí hiệu kết thúc tập tin

18

◦ Mỗi lần chỉ đọc một ký tự từ tập tin ◦ Hàm trả về mã ASCII của ký tự đọc được, trả về

Ví dụ: getc - fgetc

 Đọc các kí tự từ file và xuất ra màn hình

void main() {

FILE *fp; char ch; if ( (fp=fopen("test.txt", "r")) == NULL ) {

cout << "Cannot open file.\n"; exit(1);

} while (!feof(fp)) { ch = fgetc(fp); putchar(ch);

// in ra màn hình

} fclose(fp);

}

19

Ghi tập tin văn bản: fputs

 Hàm ghi 1 chuỗi vào tập tin: fputs

int fputs( const char *str, FILE *fp );

◦ str: chuỗi cần ghi vào tập tin ◦ fp: con trỏ tập tin

◦ Hàm trả về số >0 nếu ghi thành công, ngược lại

20

hàm trả về EOF nếu có lỗi xảy ra

Ví dụ: fputs

void main() {

char str[80]; FILE *fp; if ( (fp = fopen("teststr.txt", "w")) == NULL ) {

cout << "Cannot open file.\n"; exit(1);

} do {

/* add a newline */ // write str to file

cout << "Enter a string (CR to quit):\n"; gets(str); strcat(str, "\n"); fputs(str, fp); } while( *str!='\n' ); fclose(fp);

}

21

Đọc tập tin văn bản: fgets

 Hàm đọc 1 chuỗi từ tập tin: fgets

char *fgets( char *str, int length, FILE *fp );

◦ str: chuỗi kí tự đọc được ◦ length: số kí tự cần đọc ◦ fp: con trỏ tập tin

newline hay đã đọc được length-1 ký tự

◦ Đọc một chuỗi từ tập tin cho đến khi gặp ký tự

◦ Hàm trả về str nếu đọc thành công và một con trỏ

22

null nếu không

Ví dụ: fgets

void main() {

char str[80]; FILE *fp; if ( (fp = fopen("teststr.txt", "r")) == NULL ) {

cout << "Cannot open file.\n"; exit(1);

} while( !feof(fp) )

{

fgets (str, 80 , fp); puts (str);

}

fclose(fp);

}

23

Nội dung trình bày

1. Giới thiệu tập tin 2. Các bước xử lý tập tin 3. Đọc – Ghi tập tin văn bản (Text file) 4. Đọc – Ghi tập tin nhị phân (Binary file)

24

Ghi tập tin nhị phân: fwrite

 Hàm ghi: fwrite

int fwrite( const void *buffer, size_t size, size_t count, FILE *fp );

 Ví dụ:

◦ buffer: địa chỉ dữ liệu cần ghi ◦ size: kích thước dữ liệu muốn ghi (tính bằng byte) ◦ count: số đối tượng muốn ghi ◦ fp: con trỏ tập tin

25

fwrite(&i, sizeof(int), 1, fp);

Ghi tập tin nhị phân: fwrite

 Ví dụ: Tạo tập tin nhị phân để ghi 10 số nguyên

#include void main() {

FILE *f; f = fopen("D:\\songuyen.dat", "wb"); if ( f == NULL ) {

cout << "Cannot open file.\n"; exit(1);

} for( int i=1; i<=10; i++ )

fwrite(&i, sizeof(int), 1, f);

fclose(f);

}

26

Ghi tập tin nhị phân: fwrite

 Ví dụ: Ghi thông tin của 1 sinh viên vào tập tin #include … struct svien{

char hoten[30]; float diem;

if (fp==NULL) … fwrite(&sv1, sizeof(svien),1, fp); fclose(fp); cout<<"Da luu thanh cong";

}

}; void main() {

struct svien sv1; // cho nhập sv1… // lưu sv1 FILE *fp; fp=fopen("nhanvien.dat", "ab");

27

Chú ý: Không ghi từng thành phần của cấu trúc vào tập tin mà ghi luôn cả cấu trúc

Đọc tập tin nhị phân: fread

 Hàm ghi: fread

int fread( void *buffer, size_t size, size_t count, FILE *fp );

◦ buffer: địa chỉ dữ liệu cần ghi ◦ size: kích thước dữ liệu muốn đọc (tính bằng byte) ◦ count: số đối tượng cần đọc ◦ fp: con trỏ tập tin ◦ Hàm fread trả về số đối tượng đọc được, có thể

 Ví dụ:

dùng kết quả này để kiểm tra cuối tập tin

28

fread(&i, sizeof(int), 1, fp);

Đọc tập tin nhị phân: fread

 Ví dụ: Đọc tập tin nhị phân có chứa 10 số nguyên

và xuất chúng ra màn hình #include void main() {

int k; FILE *f = fopen("D:\\songuyen.dat", "rb"); if (f == NULL) … for( int i=1; i<=10; i++ ){

fread(&k, sizeof(int), 1, f); cout<< k<<" ";

while ( (fread(&i, sizeof(int), 1, f)) != 0) {

} fclose(f);

cout<< i<<" ";

}

}

29

Đọc tập tin nhị phân: fread

 Ví dụ: Đọc tập tin nhị phân có chứa 10 số nguyên

và xuất chúng ra màn hình #include void main() {

int k; FILE *f = fopen("D:\\songuyen.dat", "rb"); if (f == NULL) … while ( (fread(&i, sizeof(int), 1, f)) != 0) for( int i=1; i<=10; i++ ){ fread(&k, sizeof(int), 1, f); { cout<< i<<" "; cout<< k<<" ";

} } fclose(f);

}

30

Đọc tập tin nhị phân: fread

 Ví dụ: Đọc tập tin nhị phân có chứa 1 sinh viên và

xuất thông tin đọc được ra màn hình

#include … struct svien{

char hoten[30]; float diem;

fp = fopen("nhanvien.dat","rb"); fread(&sv1, sizeof(svien), 1, fp); // xuất ra màn hình cout<

}; void main(){

}

struct svien sv1; // đọc dữ liệu vào sv1 FILE *fp;

Chú ý: Khi đọc dữ liệu kiểu cấu trúc từ tập tin ta cần phải biết rõ cấu trúc đó có những thuộc tính gì và kiểu dữ liệu của mỗi thuộc tính

31

Đọc tập tin nhị phân: fseek

 Ngoài việc đọc dữ liệu kiểu tuần tự thì trong C còn cho phép đọc dữ liệu tại vị trí bất kỳ thông qua hàm: fseek int fseek( FILE *fp, long offset, int origin ); ◦ Hàm này di chuyển con trỏ file tới vị trí mong muốn ◦ fp: con trỏ tập tin ◦ offset: vị trí byte muốn chuyển đến ◦ origin:

 SEEK_SET: chuyển từ đầu tập tin  SEEK_CUR: chuyển từ vị trí hiện tại  SEEK_END: chuyển từ cuối tập tin

32

Đọc tập tin nhị phân: fseek

 Sau khi dùng hàm fseek để chuyển đến vị trí

mong muốn, muốn đọc dữ liệu ra hoặc ghi dữ liệu vào vị trí đó ta chỉ việc dùng hàm freed, hoặc hàm fwrite

 Việc truy cập phải xét xem có vượt ra ngoài kích

thước của tập tin hay không ◦ Hàm fseek cho giá trị 0 nếu không vượt ra ngoài

33

kích thước của tập tin, và cho giá trị khác 0 nếu có lỗi xảy ra

Đọc tập tin nhị phân: fseek

 Ví dụ có 100 số nguyên được lưu trong tập tin nhị

phân

◦ Muốn đọc số đầu tiên ta làm như sau:

fseek(fp, 0, SEEK_SET); fread(&x, sizeof(int), 1, fp);

◦ Muốn đọc số thứ 30 ta làm như sau:

fseek(fp, 29*sizeof(int), SEEK_SET); fread(&x, sizeof(int), 1, fp); ◦ Muốn đọc số thứ n ta làm như sau:

34

fseek(fp, (n-1)*sizeof(int), SEEK_SET); fread(&x, sizeof(int), 1, fp);

BÀI TẬP 1

Nhập 10 số nguyên và lưu vào tập tin songuyen.dat

- Đưa ra màn hình các số vừa nhập

- Nhập vào một số nguyên và kiểm tra xem có trong các số vừa nhập không? Nếu không thì đưa ra thông báo, còn nếu có thì in số nguyên đó ra

- Tạo tập tin songuyen2.dat

35

- Viết chương trình sao chép tất cả các giá trị của tập tin songuyen.dat vào tập tin songuyen2.dat

BÀI TẬP 2

- stt - Họ tên - Năm sinh - Điểm trung bình

a. Bổ sung một học sinh vào tập tin hsinh.dat: nếu tập tin chưa có thì tạo mới, nếu tập tin đã có thì bổ sung học sinh đó vào cuối tập tin

b. Tìm theo số thứ tự của học sinh: Nhập vào số thứ tự của học sinh cần tìm, hiện thông tin của học sinh tìm thấy

36

Thông tin về một học sinh gồm có :