Đọc Và Ghi File :: Thanhptran

Giới thiệu

Đọc và ghi file là những kĩ thuật quan trọng và sử dụng rất nhiều trong lập trình. Hầu như không có một ứng dụng nào có giá trị sử dụng mà không sử dụng đến những kĩ thuật này. Khi bạn làm một game, bạn cần đọc file để tải map, hoặc lưu lại điểm save. Khi làm một ứng dụng quản lý, việc lưu trữ các thông tin quan trọng vào file còn quan trọng hơn nữa. Dự án của bạn càng lớn, thì việc xử lý file càng nhiều và phức tạp. Do đó, thành thạo trong việc thao tác với file là một điều rất cần thiết.

Tiền đề bài viết

Khi tôi làm việc trên các dự án game khác nhau, tôi thường phải thao tác với rất nhiều file với nhiều định dạng như: hình ảnh, âm thanh, text… Thông qua quá trình đó, tôi đã tích lũy cho mình một số kinh nghiệm nhất định trong vấn đề này và qua bài viết này tôi muốn chia sẻ nó với các bạn.

Trong giới hạn bài viết này, tôi sử dụng ngôn ngữ C++ cùng thư viện chuẩn của C -stdio.h để bạn đọc dễ dàng hiểu rõ hơn bản chất của đọc ghi file.

Đối tượng hướng đến

Bài viết hướng đến đối tượng là lập trình viên mới làm quen với ngôn ngữ C++, và những người muốn hiểu rõ hơn về bản chất của đọc ghi file.

Mở file bằng fopen()

Công việc đầu tiên là phải include thư viện stdio.h - thư viện chuẩn của C có đầy đủ các phương thức để đọc và ghi file

Cú pháp của fopen()

  1. FILE *fopen(const char *_Filename, const char *_Mode);

Trong đó: _Filename là tên của file hoặc đường dẫn đến file cần mở. _Mode là các chế độ để xử lý file

Ta có các mode sau:

Mode Mô tả
"r" Mở một file có sẵn để đọc
"w" Tạo file mới để ghi, nếu file có sẵn thì sẽ bị ghi mới hoàn toàn
"a" Mở một file để ghi từ vị trí cuối cùng của file, nếu file không tồn tại sẽ tạo mới
"r+" Mở một file có sẵn để đọc và ghi
"w+" Tạo file mới để đọc và ghi, nếu file có sẵn thì sẽ bị ghi mới hoàn toàn
"a+" Mở một file để để đọc và ghi. Có thể đọc từ đầu file, nhưng khi ghi thì ghi từ vị trí cuối cùng của file, nếu file không tồn tại sẽ tạo mới

Ngoài ra, còn có các mode để xử lý file nhị phân như sau: “rb”, “wb”, “ab”, “rb+”, “wb+”, “ab+”, “r+b”, “a+b”

Hàm fopen() sẽ trả về NULL khi không mở được file, ví dụ trong trường hợp file bị xóa.

Đọc và ghi file thông thường

Ví dụ ta có file info.text nội dung như sau và ta muốn xuất thông tin ra màn hình:

  1. Kevin 19
  2. Brian 5
  3. Taco 8
  4. Amy 10
  5. Rye 13
  6. MinhHieu 4

Ta làm như sau:

  1. int main()
  2. {
  3. FILE *fp = fopen("info.txt", "r");
  4. if (fp == NULL)
  5. {
  6. printf("Can't open file!");
  7. }
  8. char Author[20];
  9. int NumberOfArticles;
  10. while (fscanf(fp, "%s %d", Author, &NumberOfArticles) != EOF)
  11. {
  12. printf("%s %d\n", Author, NumberOfArticles);
  13. }
  14. fclose(fp);
  15. return 0;
  16. }

Trong đó:

  1. int fscanf(const char *_Filename, const char *_Format, ...);

Hàm này có tác dụng giống như scanf(), nhưng đọc dữ liệu từ file theo _Format chứ không phải từ bàn phím như scanf(). fscanf() sẽ trả về EOF (End Of Flie) khi đọc đến cuối file.

Tương tự hàm fprintf() sẽ có chức năng tương tự như printf(), ghi dữ liệu vào file theo_Format.

Hàm fclose() là hàm bắt buộc phải sử dụng khi bạn hoàn thành thao tác với 1 file - đóng file đó lại sau khi đã xử lý xong.

Đọc và ghi file theo nhị phân

Theo như các kiến thức mà tôi nghiên cứu, thì mọi file thực chất đều là file nhị phân, vì vậytôi khuyến khích các bạn sử dụng cách này để thao tác với file.

Cách làm của tôi như sau, tôi xây dựng 1 hàm đọc để đọc file theo kiểu nhị phân, hàm sẽ trả về 1 mảng kiểu char để lưu toàn bộ dự liệu của file:

  1. char *ReadFile(const char* FilePath, long &fileSize)
  2. {
  3. FILE *pFile = fopen(FilePath, "rb");
  4. if (pFile == NULL)
  5. {
  6. return NULL;
  7. }
  8. fseek(pFile, 0, SEEK_END);
  9. fileSize = ftell(pFile);
  10. fseek(pFile, 0, SEEK_SET);
  11. char *buff = new char[fileSize];
  12. fread(buff, fileSize, 1, pFile);
  13. fclose(pFile);
  14. return buff;
  15. }

Ta chú ý một số điểm sau:

  1. fseek(pFile, 0, SEEK_END);

Bạn tưởng tượng có 1 con trỏ văn bản đang nhấp nháy ở trong file, thì hàm này sẽ đưa vị trí của con trỏ đó về cuối file.

  1. fileSize = ftell(pFile);

Hàm ftell() sẽ trả về số bytes tính từ đầu file đến vị trí của con trỏ văn bản, do tác dụng của hàm fseek() phía trên mà ta sẽ lấy được kích thước của file.

  1. fseek(pFile, 0, SEEK_SET);

Hàm này sẽ đưa vị trí của con trỏ đó về đầu file.

  1. size_t fread(void *ptr, size_t size_of_elements,
  2. size_t size_of_an_element,
  3. FILE *_File);

Ta dùng hàm fread() để đọc dữ liệu từ File vào mảng ptr, với tham số truyền vào là tổng kích thước cần đưa và kích thước của từng phần tử dữ liệu, ở đây ta dùng mảng char và muốn đưa toàn bộ nên hàm sẽ là

  1. fread(buff, fileSize, 1, pFile);

Tương tự ta ghi 1 file, ví dụ ta ghi dòng chữ Hello World! vào file D:\hello.txt theo kiểu nhị phân như sau:

  1. FILE *pFile = fopen("hello.txt", "wb");
  2. if (pFile == NULL)
  3. {
  4. printf("Can't open file!");
  5. return;
  6. }
  7. char *Hello = "Hello World!";
  8. fwrite(Hello, strlen(Hello), 1, pFile);
  9. fclose(pFile);

Source <https://www.stdio.vn/articles/read/108-can-ban-ve-doc-va-ghi-file-trong-ngon-ngu-c>

a. Khai báo

FILE *< tên biến >; Ví dụ : FILE *f; // Khai bao bien con tro file f

b. Mở tập tin

fopen (< đường dẫn tên tập tin> , < kiểu truy nhập >);

Ví dụ : FILE *f; // Khai bao bien con tro f

f = fopen ( “C:\\VD1.txt” , “rt” ) ;

Các kiểu truy nhập tập tin thông dụng:

t là kiểu truy nhập tập tin đối với dạng tập tin văn bản (text).

b là kiểu truy nhập tập tin đối với dạng tập tin nhị phân (binary).

r mở ra để đọc ( ready only).

w mở ra để ghi (create / write).

a mở ra để them vào (append).

r+ mở ra để đọc và ghi (modify).

c. Các hàm đọc ghi nội dung tập tin

- See more at: https://expressmagazine.net/development/1756/huong-dan-lam-viec-voi-tap-tin-trong-c#sthash.v5Z0cYiO.pczZV4kS.dpuf

>>Đọc thêm<<

a. Khai báo

FILE *< tên biến >;

Ví dụ : FILE *f; // Khai bao bien con tro file f

b. Mở tập tin

fopen (< đường dẫn tên tập tin> , < kiểu truy nhập >);

Ví dụ : FILE *f; // Khai bao bien con tro f

f = fopen ( “C:\\VD1.txt” , “rt” ) ;

Các kiểu truy nhập tập tin thông dụng:

t là kiểu truy nhập tập tin đối với dạng tập tin văn bản (text).

b là kiểu truy nhập tập tin đối với dạng tập tin nhị phân (binary).

r mở ra để đọc ( ready only).

w mở ra để ghi (create / write).

a mở ra để them vào (append).

r+ mở ra để đọc và ghi (modify).

c. Các hàm đọc ghi nội dung tập tin

Tập tin văn bản

+ Đọc tập tin

STT

TÊN HÀM

Ý NGHĨA SỬ DỤNG

VÍ DỤ

1

fscanf(<FILE *>, <định dạng>, <các tham biến>);

Dữ liệu từ một tập tin theo định dạng.

fscanf(f, “%d”, &x);

2

fgets(<vùng nhớ>, <kích

thước tối đa>, <FILE *>);

Đọc một chuỗi ký tự từ một tập tin với kích thước tối đa cho phép, hoặc gặp ký tự xuống dòng.

char s[80];

fgets(s, 80, f);

getc(< FILE * >);

Đọc một ký tự từ tập tin đang mở.

char c=getc(f);

+ Ghi tập tin

STT

TÊN HÀM

Ý NGHĨA SỬ DỤNG

VÍ DỤ

1

fprintf(<FILE *>, <định

dạng>[, <các tham biến>]);

Ghi dữ liệu theo một định dạng nào đó vào tập tin.

fprintf(f,“%d”,x);

2

fputs(<chuỗi ký tự>, <FILE

*>);

Ghi một chuỗi ký tự vào tập

tin đang mở.

fputs(“Giao trinh BT”, f);

Tập tin nhị phân

+ Đọc tập tin

STT

TÊN HÀM

Ý NGHĨA SỬ DỤNG

VÍ DỤ

1

fread(<&ptr>, <size>, <len>, <FILE *>);

• ptr: vùng nhớ để lưu dữ liệu đọc.

• size: kích thước mỗi ô nhớ (tính bằng byte).

• len: độ dài dữ liệu cần đọc.

FILE: đọc từ tập tin nhị

int a[30], b, n;

fread(a,sizeof(int), n , f);

Fread(&b, sizeof(int), 1 , f);

+ Ghi tập tin

STT

TÊN HÀM

Ý NGHĨA SỬ DỤNG

VÍ DỤ

1

fwrite(<&prt>, <size>, <len>,<FILE *> );

Tham số tương tự như hàm fread.

fwrite(a, sizeof(int), n , f);

Đóng tập tin

Sau khi không còn làm việc với tập tin, để đảm bảo an toàn cho dữ liệu thì nhất thiết ta phải đóng tập tin lại.

fclose ( < biến con trỏ tập tin > ) ;

hoặc fcloseall () ;

Ví dụ : fclose (f) ;

Các thao tác khác trên tập tin

* Xoá tập tin :

remove ( < đường dẫn tập tin> );

* Đổi tên tập tin :

rename ( < tên tập tin cũ >, < tên tập tin mới > );

- See more at: https://expressmagazine.net/development/1756/huong-dan-lam-viec-voi-tap-tin-trong-c#sthash.v5Z0cYiO.dpuf

ập tin văn bản

+ Đọc tập tin

STT

TÊN HÀM

Ý NGHĨA SỬ DỤNG

VÍ DỤ

1

fscanf(<FILE *>, <định dạng>, <các tham biến>);

Dữ liệu từ một tập tin theo định dạng.

fscanf(f, “%d”, &x);

2

fgets(<vùng nhớ>, <kích

thước tối đa>, <FILE *>);

Đọc một chuỗi ký tự từ một tập tin với kích thước tối đa cho phép, hoặc gặp ký tự xuống dòng.

char s[80];

fgets(s, 80, f);

getc(< FILE * >);

Đọc một ký tự từ tập tin đang mở.

char c=getc(f);

+ Ghi tập tin

STT

TÊN HÀM

Ý NGHĨA SỬ DỤNG

VÍ DỤ

1

fprintf(<FILE *>, <định

dạng>[, <các tham biến>]);

Ghi dữ liệu theo một định dạng nào đó vào tập tin.

fprintf(f,“%d”,x);

2

fputs(<chuỗi ký tự>, <FILE

*>);

Ghi một chuỗi ký tự vào tập

tin đang mở.

fputs(“Giao trinh BT”, f);

Tập tin nhị phân

+ Đọc tập tin

STT

TÊN HÀM

Ý NGHĨA SỬ DỤNG

VÍ DỤ

1

fread(<&ptr>, <size>, <len>, <FILE *>);

• ptr: vùng nhớ để lưu dữ liệu đọc.

• size: kích thước mỗi ô nhớ (tính bằng byte).

• len: độ dài dữ liệu cần đọc.

FILE: đọc từ tập tin nhị

int a[30], b, n;

fread(a,sizeof(int), n , f);

Fread(&b, sizeof(int), 1 , f);

+ Ghi tập tin

STT

TÊN HÀM

Ý NGHĨA SỬ DỤNG

VÍ DỤ

1

fwrite(<&prt>, <size>, <len>,<FILE *> );

Tham số tương tự như hàm fread.

fwrite(a, sizeof(int), n , f);

d. Đóng tập tin

Sau khi không còn làm việc với tập tin, để đảm bảo an toàn cho dữ liệu thì nhất thiết ta phải đóng tập tin lại.

fclose ( < biến con trỏ tập tin > ) ;

hoặc fcloseall () ;

Ví dụ : fclose (f) ;

e. Các thao tác khác trên tập tin

* Xoá tập tin :

remove ( < đường dẫn tập tin> );

* Đổi tên tập tin :

rename ( < tên tập tin cũ >, < tên tập tin mới > );

- See more at: https://expressmagazine.net/development/1756/huong-dan-lam-viec-voi-tap-tin-trong-c#sthash.v5Z0cYiO.dpuf

ập tin văn bản

+ Đọc tập tin

STT

TÊN HÀM

Ý NGHĨA SỬ DỤNG

VÍ DỤ

1

fscanf(<FILE *>, <định dạng>, <các tham biến>);

Dữ liệu từ một tập tin theo định dạng.

fscanf(f, “%d”, &x);

2

fgets(<vùng nhớ>, <kích

thước tối đa>, <FILE *>);

Đọc một chuỗi ký tự từ một tập tin với kích thước tối đa cho phép, hoặc gặp ký tự xuống dòng.

char s[80];

fgets(s, 80, f);

getc(< FILE * >);

Đọc một ký tự từ tập tin đang mở.

char c=getc(f);

+ Ghi tập tin

STT

TÊN HÀM

Ý NGHĨA SỬ DỤNG

VÍ DỤ

1

fprintf(<FILE *>, <định

dạng>[, <các tham biến>]);

Ghi dữ liệu theo một định dạng nào đó vào tập tin.

fprintf(f,“%d”,x);

2

fputs(<chuỗi ký tự>, <FILE

*>);

Ghi một chuỗi ký tự vào tập

tin đang mở.

fputs(“Giao trinh BT”, f);

Tập tin nhị phân

+ Đọc tập tin

STT

TÊN HÀM

Ý NGHĨA SỬ DỤNG

VÍ DỤ

1

fread(<&ptr>, <size>, <len>, <FILE *>);

• ptr: vùng nhớ để lưu dữ liệu đọc.

• size: kích thước mỗi ô nhớ (tính bằng byte).

• len: độ dài dữ liệu cần đọc.

FILE: đọc từ tập tin nhị

int a[30], b, n;

fread(a,sizeof(int), n , f);

Fread(&b, sizeof(int), 1 , f);

+ Ghi tập tin

STT

TÊN HÀM

Ý NGHĨA SỬ DỤNG

VÍ DỤ

1

fwrite(<&prt>, <size>, <len>,<FILE *> );

Tham số tương tự như hàm fread.

fwrite(a, sizeof(int), n , f);

d. Đóng tập tin

Sau khi không còn làm việc với tập tin, để đảm bảo an toàn cho dữ liệu thì nhất thiết ta phải đóng tập tin lại.

fclose ( < biến con trỏ tập tin > ) ;

hoặc fcloseall () ;

Ví dụ : fclose (f) ;

e. Các thao tác khác trên tập tin

* Xoá tập tin :

remove ( < đường dẫn tập tin> );

* Đổi tên tập tin :

rename ( < tên tập tin cũ >, < tên tập tin mới > );

- See more at: https://expressmagazine.net/development/1756/huong-dan-lam-viec-voi-tap-tin-trong-c#sthash.v5Z0cYiO.dpuf

Từ khóa » đọc File đó