Mở và đóng file trong C (fopen, fopen_s, fclose) | Laptrinhcanban.com

HOME › >>

Mở và đóng file trong C (fopen, fopen_s, fclose)

Cùng tìm hiểu về cách mở file và đóng file trong C. Bạn sẽ học được cách mở một file trong C bằng 2 hàm có sẵn là fopen và fopen_s, cũng như cách đóng file trong C bằng hàm fclose sau bài học này.

Chúng ta có 2 phương pháp để mở file trong C như sau:

  • Mở file bằng hàm fopen
  • Mở file bằng hàm fopen_s

Và chúng ta dùng hàm fclose trong C để đóng một file, sau khi đã hoàn thành các xử lý với nó.

Bài viết này sẽ chú trọng về cách mở file trong C. Về quy trình tổng quát xử lý file trong C, hãy tham khảo tại bài sau:

Mở file trong C bằng hàm fopen

Hàm fopen trong C

Hàm fopen trong C là một hàm có sẵn trong thư viện chuẩn, có tác dụng mở file trong C. Tên hàm fopen được viết tắt bởi cụm từ fileopen, được dịch theo tiếng Việt chính xác là hàm mở file.

Đây là một hàm không thể thiếu khi chúng ta muốn thao tác xử lý với file trong C.

Có 2 loại hàm fopen trong C là hàm fopen thông thường và hàm fopen_s cao cấp. Hàm fopen_s là một phiên bản an toàn và bảo mật hơn của hàm fopen, và chúng ta sẽ tìm hiểu về nó ở phần sau.

Chúng ta sử dụng hàm fopen thông thường trong C với cú pháp sau đây:

fp = fopen(filepath, mode);

Trong đó:

  • fp là con trỏ file dùng để gán kiểu cấu trúc FILE được trả về từ hàm nếu mở file thành công
  • filepath là đường dẫn tới file cần mở. Đường dẫn này có thể là đường dẫn tương đối, hoặc là đường dẫn tuyệt đối.
  • mode là chế độ mở file.

Hàm fopen sẽ trả về một thực thể được tạo ra từ kiểu cấu trúc FILE chứa các thông tin của file đã mở để chúng ta có thể xử lý file. Chúng ta cũng gọi thực thể này là file handle - một đối tượng để xủ lý file trong C. Nếu mở file thất bại, một giá trị NULL sẽ được trả về.

Việc mở file và gán địa chỉ file vào con trỏ thường được tiến hành đồng thời. Ví dụ bạn có thể mở file sample.txt có sẵn bằng hàm fopen() với mode r và gán vào con trỏ file fp như sau:

#include <stdio.h>

int main(void)
{
//Khai báo con trỏ file
FILE * fp = NULL;

//Mở file và gán file handle vào con trỏ file
fp = fopen("sample.txt", "r");

return 0;
}

Các mode để mở file trong C

Các chế độ có thể sử dụng để mở file bằng hàm fopen trong C như sau:

ModeXử lýChức năng
rMở để đọcChỉ cho phép đọc file
Nếu file không tồn tại thì trả về NULL
wMở để ghi đèXoá nội dung cũ và ghi đè nội dung mới
Nếu file không tồn tại thì tạo file mới
aMở để ghi chènGhi chèn nội dung mới vào cuối file
Nếu file không tồn tại thì tạo file mới
r+Mở để đọc và ghi đèCho phép cả đọc và ghi đè
Nếu file không tồn tại thì trả về NULL
w+Mở để đọc và ghi đèCho phép cả đọc và ghi đè
Nếu file không tồn tại thì tạo file mới
a+Mở để đọc và ghi chènCho phép cả đọc và ghi chèn
Nếu file không tồn tại thì tạo file mới

Mở file binary file trong C

Lại nữa, bằng cách thêm ký tự b vào đằng trước tên mode thì chúng ta cũng có thể mở các binary file - tập tin nhị phân trong C. Khác với các tập tin văn bản mà chúng ta có thể đọc được các chữ cái, văn bản ghi trong đó, thì Binary File là một tập tin chứa nội dung là các chuỗi nhị phân như sau:
binary file

Các mode dùng để mở binary file trong C sẽ là:

ModeXử lýChức năng
rbĐọcChế độ đọc file binary
wbGhi đèChế độ ghi đè file binary
abGhi chènChế độ ghi chèn file binary

Mở file trong C bằng hàm fopen_s

Hàm fopen_s trong C là một phiên bản an toàn và bảo mật hơn của hàm fopen, và hàm này cũng giúp chúng ta mở file trong C.

Chúng ta sử dụng hàm fopen_s trong C với cú pháp sau đây:

errno_t err = fopen_s(fp, filepath, mode);

Trong đó:

  • errno_t là kiểu lỗi trong C, và err là tên biến để gán giá trị lỗi nếu mở file thất bại
  • fp là con trỏ file dùng để gán kiểu cấu trúc FILE được trả về từ hàm nếu mở file thành công
  • filepath là đường dẫn tới file cần mở. Đường dẫn này có thể là đường dẫn tương đối, hoặc là đường dẫn tuyệt đối.
  • mode là chế độ mở file. Các mode có thể dùng tương tự như với hàm fopen mà chúng ta đã học ở trên.

Hàm fopen_s sẽ trả về một số tự nhiên biểu thị số hiệu của lỗi khi mở file. Nếu số này bằng 0 thì việc mở file thành công, và nếu số này khác 0 thì chúng ta có thể tìm ra nội dung lỗi bằng cách đối chiếu số hiệu của lỗi với bảng lỗi.

Trong trường hợp không cần xác định tới kiểu lỗi nếu có khi mở file, chúng ta cũng có thể lược bỏ đi việc gán errno_t err mà dùng hàm trực tiếp với cú pháp sau đây:

fopen_s(fp, filepath, mode);

Sau khi mở file thành công, thực thể được tạo ra từ kiểu cấu trúc FILE chứa các thông tin của file đã mở sẽ được gán vào con trỏ fp đã khai báo. Và chúng ta có thể thực hiện các thao tác với file thông qua con trỏ file này như bình thường.

Ví dụ cụ thể, chúng ta mở file bằng hàm fopen_s như sau:

#include <stdio.h>

int main(void){
//Mở file bằng hàm fopen_s mà không kiểm tra lỗi
FILE * fp1 = NULL;
fopen_s(&fp1, "sample.txt", "r");
fclose(fp1);


//Mở file bằng hàm fopen_s có kiểm tra lỗi
FILE * fp2 = NULL;
errno_t no2;

no2 = fopen_s(&fp2, "memo.txt", "w");
if (no2 != 0) printf("%s\n", "Mo file thanh cong");
fclose(fp2);
}

Sự khác biệt giữa hàm fopen và fopen_s

Hàm fopen_s là một phiên bản an toàn và bảo mật hơn của hàm fopen. Do đó, hàm này cấm mở một file cùng lúc khi đang mở file đó ở chế độ ghi.

Bởi vậy, nếu chúng ta đã mở một file bằng hàm fopen_s rồi thì chương trình tiếp sẽ kết thúc bất thường vào lần gọi thứ hai của hàm fopen_s.

Sự khác biệt lớn nhất giữa giữa hàm fopen và fopen_s cũng chính là điều này. Chúng ta có thể mở một file cùng lúc khi đang mở file đó ở chế độ ghi bằng hàm fopen, nhưng sẽ xảy ra lỗi nếu chúng ta làm việc này với hàm fopen_s.

Ví dụ, do hàm fopen_s được gọi 2 lần với cùng môt file, nên chương trình sẽ tự động kết thúc như sau:

#include <stdio.h>

int main(void)
{
FILE * fp1 = NULL;
FILE * fp2 = NULL;
errno_t no1;
errno_t no2;

//Lần mở file đầu tiên với fopen_s
no1 = fopen_s(&fp1, "memo.txt", "w");
if (no1 != 0)
{
printf("ERR(%d): mo lan 1", no1);
}

//Lần mở cùng một file thứ 2 với fopen_s
no2 = fopen_s(&fp2, "memo.txt", "w");
if (no2 != 0)
{
printf("ERR(%d): mo lan 2", no2);
}

return 0;
}

Kết quả chương trình xuất hiện lỗi và sẽ tự kết thúc như sau:

RR(13): mo lan 2

Xử lý lỗi khi mở file trong C

Như đã phân tích trong bài Xử lý file trong c thì chúng ta cần phải xử lý lỗi khi mở một file thất bại trong C, để chương trình tự xử lý lỗi, và chạy chương trình một cách chính xác.

Và để xử lý lỗi khi mở file trong C, chúng ta hay sử dụng tới cách viết như sau đây:

//Mở file bằng hàm fopen, và trả về NULL nếu mở file thất bại.
fp = fopen(fname, "r");
if(fp == NULL) {
printf("%s file not open!\n", fname);
exit(0);
}

Lưu ý nếu bạn mở file bên trong hàm main(), thì bằng cách dùng lệnh return như sau thì chúng ta cũng có thể xử lý lỗi khi mở file trong C:

//Mở file bằng hàm fopen, và trả về NULL nếu mở file thất bại.
fp = fopen(fname, "r");
if(fp == NULL) {
printf("%s file not open!\n", fname);
return -1;
}

Tạo file mới trong C

Bằng cách sử dụng một trong 2 hàm mở file trên, chúng ta có thể tạo một file mới và mở nó ra để xử lý. Ví dụ chúng ta sẽ tạo một file mới có tên sample.txt bằng hàm fopen() với mode w như sau:

#include <stdio.h>

int main(void)
{
FILE * fp = NULL; //Khai báo con trỏ file
fp = fopen("sample.txt", "w"); // Mở file và gán file handle vào con trỏ file

return 0;
}

Bạn cũng có thể sử dụng mode a+ để tạo file mới trong C:

#include <stdio.h>

int main(void)
{
FILE * fp = NULL; //Khai báo con trỏ file
fp = fopen("sample.txt", "a+"); // Mở file và gán file handle vào con trỏ file

return 0;
}

Sau khi compile và chạy chương trình, một file trống memo.txt với kích thước 0 KB sẽ được tạo ra như dưới đây:
Mở và tạo file mới bằng fopen trong C

Đóng file trong C bằng hàm fclose

Sau khi đã thao tác xong với file trong C, chúng ta cần đóng file đó lại để kết thúc phiên làm việc với file và giải phóng bộ nhớ trong chương trình.

Và để đóng file trong C chúng ta sẽ dùng tới hàm fclose.

Hàm fclose là một hàm có sẵn trong thư viện chuẩn, có tác dụng đóng một file đã mở từ trước đó. Tên hàm fclose được viết tắt bởi cụm từ fileclose, được dịch theo tiếng Việt chính xác là hàm đóng file.

Chúng ta sử dụng hàm fclose trong C với cú pháp sau đây:

int fclose(FILE * fp);

Trong đó fp là con trỏ của file cần đóng.

Hàm fclose sẽ trả về 0 trong trường hợp kết thúc file bình thường. Và một giá trị kiểu EOF được trả lại trong trường hợp kết thúc file bất thường.

Ví dụ cụ thể, chúng ta đóng một file sau khi đã mở và hoàn thành các xử lý với nó như sau:

#include <stdio.h>

int main(void){
//Mở file
FILE * fp = NULL;
fp = fopen("memo.txt", "w");

//Đóng file
fclose(fp);

return 0;
}

Tại sao phải đóng file sau khi đã mở file

C là ngôn ngữ sẽ tự động đóng file đang làm việc và giải phóng bộ nhớ sau khi chương trình kết thúc. Bởi vậy nếu trong chương trình chúng ta chỉ sử dụng file có 1 lần duy nhất, thì chúng ta không cần đóng nó sau khi mở, vì file sẽ tự động đóng khi kết thúc chương trình.

Tuy nhiên khi đang ở giữa chương trình C, khi chúng ta bắt đầu các xử lý mở 1 file để đọc hoặc ghi file thì file đó sẽ rơi vào trạng thái bị khóa nhằm ngăn chặn chương trình hoặc phần mềm khác trên hệ điều hành truy cập cùng lúc vào file, gây nên các chồng chéo trong xử lý.

Để có các chương trình và phần mềm khác có thể truy cập vào file thì sau khi kết thúc một phiên làm việc với file trong chương trình C, chúng ta nên đóng nó lại và mở lại nó vào thời điểm khác khi cần thiết.

Ngoài ra việc đóng file cũng sẽ giải phóng bộ nhớ khi chương trình đang chạy, giúp tiết kiệm và sử dụng bộ nhớ máy tính hiệu quả hơn.

Bởi vậy, chúng ta nên tự tạo thói quen đóng file sau khi đã mở file mà không còn cần xử lý file đó nữa.

Tổng kết

Trên đây Kiyoshi đã hướng dẫn các bạn về cách mở file và đóng file trong C rồi. Để nắm rõ nội dung bài học hơn, bạn hãy thực hành viết lại các ví dụ của ngày hôm nay nhé.

Và hãy cùng tìm hiểu những kiến thức sâu hơn về C trong các bài học tiếp theo.

URL Link

https://laptrinhcanban.com/c/lap-trinh-c-co-ban/file-trong-c/mo-dong-file-trong-c/

Hãy chia sẻ và cùng lan tỏa kiến thức lập trình Nhật Bản tại Việt Nam!

HOME  › >>

Profile
きよしです!笑

Tác giả : Kiyoshi (Chis Thanh)

Kiyoshi là một cựu du học sinh tại Nhật Bản. Sau khi tốt nghiệp đại học Toyama năm 2017, Kiyoshi hiện đang làm BrSE tại Tokyo, Nhật Bản.