Ngôn ngữ C cung cấp nhiều hàm đọc tệp, phổ biến nhất là read() và fread(). Ngoài ra còn có getchar() để đọc từng ký tự. Việc nắm vững các hàm xử lý tệp, cách gọi, tham số đầu vào/ra là cần thiết để lưu trữ và xử lý thông tin trên hệ thống.
Bài viết này trên Linuxhint sẽ hướng dẫn bạn sử dụng hàm read() để đọc tệp, bao gồm cú pháp, mô tả hoạt động, các tham số, kiểu dữ liệu và cách khai báo đúng đắn. Sau đó áp dụng vào ví dụ thực tế. Cuối cùng có phần chuyên biệt về phát hiện và xác định lỗi khi dùng read().
Cú pháp hàm read()
size_t read(int fd, void *buf, size_t count);
Mô tả hàm read()
Hàm read() đọc nội dung của tệp đã mở được chỉ định bởi bộ mô tả tệp (file descriptor) trong tham số fd. Nó sao chép dữ liệu vào bộ đệm trỏ bởi buf với số byte là count. fd là số nguyên trả về bởi open() khi mở tệp.
Nếu thành công, read() trả về số byte đã đọc. Trả về 0 nghĩa là đã đọc hết tệp (EOF), -1 nghĩa là xảy ra lỗi. Mã lỗi cụ thể được lưu trong biến toàn cục errno (khai báo trong errno.h). Phần sau sẽ mô tả các lỗi thường gặp và cách xử lý.
Hàm read() được khai báo trong unistd.h. Để sử dụng, cần include:
#include <unistd.h>
Ví dụ: Đọc tệp với read()
Chúng ta tạo tệp example.txt trong thư mục Documents chứa đoạn văn đầu tiên của bài viết. Các bước:
- Include các header cần thiết:
stdio.h,stdlib.h,unistd.h,fcntl.h. - Khai báo
fd(file descriptor), bộ đệmbuff[1024], mảngpathlưu đường dẫn tệp. - Gọi
open(path, O_RDONLY)để mở tệp chỉ đọc, lưu descriptor vàofd. - Gọi
read(fd, buff, 1024)đọc nội dung vàobuff. - In ra màn hình bằng
printf.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main() {
int fd;
char buff[1024];
char path[] = "Documents/example.txt";
fd = open(path, O_RDONLY);
read(fd, buff, 1024);
printf("\n\n%s\n\n", buff);
return 0;
}

Phát hiện và xác định lỗi
Khi read() trả về -1, có lỗi. Cách đơn giản nhất là kiểm tra bằng if:
int n = read(fd, buff, 1024);
if (n == -1) {
printf("Lỗi khi đọc tệp.\n");
}
Mã lỗi lưu trong errno (include errno.h). Dùng switch trên errno để xác định lỗi. Bảng dưới liệt kê một số lỗi phổ biến:
| Định nghĩa | Giá trị errno | Mô tả |
|---|---|---|
| EAGAIN | 11 | Thử lại |
| EBADF | 9 | Số tệp không hợp lệ |
| EDESTADDRREQ | 89 | Yêu cầu địa chỉ đích |
| EFAULT | 14 | Địa chỉ không đúng |
| EFBIG | 27 | Tệp quá lớn |
| EINTR | 4 | Lời gọi hệ thống bị ngắt |
| EINVAL | 22 | Tham số không hợp lệ |
| EIO | 5 | Lỗi I/O |
| EPERM | 1 | Thao tác không được phép |
Ví dụ: truyền descriptor âm (99999999) để gây lỗi, dùng switch xác định:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
int main() {
int fd, n;
char buff[1024];
char path[] = "Documents/example.txt";
fd = open(path, O_RDONLY);
n = read(99999999, buff, 1024);
if (n == -1) {
switch(errno) {
case EBADF:
printf("Số tệp không hợp lệ. Lỗi: %i\n", errno);
break;
case EINVAL:
printf("Tham số không hợp lệ. Lỗi: %i\n", errno);
break;
case EIO:
printf("Lỗi I/O. Lỗi: %i\n", errno);
break;
}
}
return 0;
}

Kết quả cho thấy lỗi EBADF khi descriptor không hợp lệ.
Kết luận
Bài viết đã trình bày cách dùng read(), cú pháp, lý thuyết, ví dụ thực tế mở/đọc tệp, và phương pháp phát hiện/xác định lỗi qua errno.