Câu trả lời:
Bộ mô tả tệp là một "xử lý" số nguyên cấp thấp được sử dụng để xác định một tệp đã mở (hoặc ổ cắm, hoặc bất cứ thứ gì) ở cấp nhân, trong Linux và các hệ thống giống Unix khác.
Bạn chuyển các bộ mô tả tệp "trần trụi" cho các lệnh gọi Unix thực tế, chẳng hạn như read()
, write()
v.v.
Con FILE
trỏ là một cấu trúc cấp thư viện tiêu chuẩn C, được sử dụng để biểu diễn một tệp. Phần này FILE
bao bọc bộ mô tả tệp, đồng thời thêm bộ đệm và các tính năng khác để làm cho I / O dễ dàng hơn.
Bạn chuyển FILE
con trỏ đến các hàm C tiêu chuẩn chẳng hạn như fread()
và fwrite()
.
fd
là đối số đầu tiên read()
. Tại sao bạn gọi nó là khỏa thân?
FILE *
kiểu của thư viện tiêu chuẩn , bộ mô tả tệp số nguyên "ít được bọc hơn", tức là "trần trụi".
Một cái được đệm ( FILE *
) và cái kia thì không. Trong thực tế, bạn muốn sử dụngFILE *
hầu như luôn luôn khi bạn đang đọc từ một tệp 'thực' (tức là trên ổ đĩa), trừ khi bạn biết mình đang làm gì hoặc trừ khi tệp của bạn thực sự là một ổ cắm hoặc tương tự ..
Bạn có thể lấy bộ mô tả tệp từ việc FILE *
sử dụng fileno()
và bạn có thể mở bộ đệm FILE *
từ bộ mô tả tệp bằng cách sử dụngfdopen()
Bộ mô tả tệp chỉ là một số nguyên mà bạn nhận được từ open()
cuộc gọi POSIX . Sử dụng C tiêu chuẩn, fopen()
bạn nhận được một FILE
cấu trúc trở lại. Cấu FILE
trúc chứa bộ mô tả tệp này cùng với những thứ khác như chỉ báo lỗi và phần cuối của tệp, vị trí luồng, v.v.
Vì vậy, sử dụng fopen()
cung cấp cho bạn một lượng trừu tượng nhất định so với open()
. Nói chung, bạn nên sử dụng fopen()
vì nó dễ di động hơn và bạn có thể sử dụng tất cả các hàm C tiêu chuẩn khác sử dụng FILE
struct, tức là fprintf()
và family.
Không có vấn đề về hiệu suất khi sử dụng.
Trình mô tả tệp so với Con trỏ tệp
Bộ mô tả tệp:
File Descriptor là một giá trị số nguyên được trả về bởi open()
lệnh gọi hệ thống.
int fd = open (filePath, mode);
Con trỏ tệp:
Con trỏ tệp là một con trỏ đến một cấu trúc C được trả về bởi fopen()
hàm thư viện, được sử dụng để xác định tệp, gói bộ mô tả tệp, chức năng đệm và tất cả các chức năng khác cần thiết cho hoạt động I / O. Con trỏ tệp thuộc loại FILE , có định nghĩa có thể được tìm thấy trong "/usr/include/stdio.h" . Định nghĩa này có thể thay đổi từ trình biên dịch này sang trình biên dịch khác.
FILE *fp = fopen (filePath, mode);
// A FILE Structure returned by fopen
typedef struct
{
unsigned char *_ptr;
int _cnt;
unsigned char *_base;
unsigned char *_bufendp;
short _flag;
short _file;
int __stdioid;
char *__newbase;
#ifdef _THREAD_SAFE
void *_lock;
#else
long _unused[1];
#endif
#ifdef __64BIT__
long _unused1[4];
#endif /* __64BIT__ */
} FILE;
Muốn thêm điểm có thể hữu ích.
TRONG KHOẢNG FILE *
Tôi sử dụng nó nhiều lần cho các bản ghi gỡ lỗi. thí dụ,
FILE *fp;
fp = fopen("debug.txt","a");
fprintf(fp,"I have reached till this point");
fclose(fp);
TRONG KHOẢNG FILE DESCRIPTOR
Nó thường được sử dụng cho IPC.
Cung cấp quyền kiểm soát cấp thấp cho các tệp trên hệ thống * nix. (Thiết bị, tệp, ổ cắm, v.v.), do đó mạnh mẽ hơn FILE *
.
fdopen()
để làm những việc như IPC và các thiết bị với FILE*
?
FILE*
, nhưng bạn có thể tạo một FILE*
từ bộ mô tả tệp ( fdopen()
) và sau đó việc đóng lại FILE
cũng sẽ đóng bộ mô tả. Do đó, bạn có thể thực hiện IPC, nhưng bạn phải xử lý các bộ mô tả tệp một chút để tạo điều kiện thuận lợi cho bất kỳ IPC trực tiếp nào.
FILE *
là hữu ích hơn khi bạn làm việc với các tập tin văn bản và sử dụng đầu vào / đầu ra, bởi vì nó cho phép bạn sử dụng các hàm API như sprintf()
, sscanf()
, fgets()
, feof()
, vv
API trình mô tả tệp là cấp thấp, vì vậy nó cho phép làm việc với các ổ cắm, đường ống, tệp được ánh xạ bộ nhớ (tất nhiên và các tệp thông thường).
Chỉ cần một ghi chú để kết thúc cuộc thảo luận (nếu quan tâm) ....
fopen
có thể không an toàn và bạn có thể nên sử dụng fopen_s
hoặc open
với bộ bit độc quyền. C1X đang cung cấp x
các chế độ, vì vậy bạn có thể fopen
với các chế độ "rx"
,"wx"
vv
Nếu bạn sử dụng open
, bạn có thể cân nhắc open(..., O_EXCL | O_RDONLY,... )
hoặcopen(..., O_CREAT | O_EXCL | O_WRONLY,... )
.
Ví dụ, hãy xem Không đưa ra giả định về fopen () và việc tạo tệp .
fopen_s
dường như không có sẵn với POSIX
, tôi giả sử các soultion cầm tay nhất sẽ được open(2)
rồi fdopen(2)
. (để cửa sổ sang một bên). Ngoài ra, điều gì sẽ nhanh hơn fopen_s()
hoặc open(2)
theo sau là fdopen(2)
gì?
Ví dụ: các cuộc gọi hệ thống chủ yếu sử dụng bộ mô tả tệp read
và write
. Hàm thư viện sẽ sử dụng con trỏ tệp ( printf
, scanf
). Tuy nhiên, các hàm thư viện chỉ sử dụng các lệnh gọi nội bộ của hệ thống.
Tôi đã tìm thấy một nguồn tốt ở đây , cung cấp tổng quan cấp cao về sự khác biệt giữa hai:
Khi bạn muốn nhập hoặc xuất tệp, bạn có hai cơ chế cơ bản để biểu diễn kết nối giữa chương trình và tệp: bộ mô tả tệp và luồng. Bộ mô tả tệp được biểu diễn dưới dạng đối tượng kiểu int, trong khi luồng được biểu diễn dưới dạng đối tượng FILE *.
Bộ mô tả tệp cung cấp một giao diện nguyên thủy, cấp thấp cho các hoạt động đầu vào và đầu ra. Cả bộ mô tả tệp và luồng đều có thể đại diện cho kết nối với một thiết bị (chẳng hạn như thiết bị đầu cuối) hoặc một đường ống hoặc ổ cắm để giao tiếp với một quy trình khác, cũng như một tệp bình thường. Tuy nhiên, nếu bạn muốn thực hiện các hoạt động điều khiển dành riêng cho một loại thiết bị cụ thể, bạn phải sử dụng bộ mô tả tệp; không có phương tiện để sử dụng các luồng theo cách này. Bạn cũng phải sử dụng bộ mô tả tệp nếu chương trình của bạn cần thực hiện đầu vào hoặc đầu ra ở các chế độ đặc biệt, chẳng hạn như đầu vào không chặn (hoặc bỏ phiếu) (xem Cờ trạng thái tệp).
Các luồng cung cấp giao diện cấp cao hơn, được xếp lớp trên các cơ sở trình mô tả tệp nguyên thủy. Giao diện luồng xử lý tất cả các loại tệp khá giống nhau — ngoại lệ duy nhất là ba kiểu đệm mà bạn có thể chọn (xem Phần đệm luồng).
Ưu điểm chính của việc sử dụng giao diện luồng là tập hợp các chức năng để thực hiện các hoạt động đầu vào và đầu ra thực tế (trái ngược với các hoạt động điều khiển) trên các luồng phong phú và mạnh mẽ hơn nhiều so với các phương tiện tương ứng cho bộ mô tả tệp. Giao diện bộ mô tả tệp chỉ cung cấp các chức năng đơn giản để chuyển các khối ký tự, nhưng giao diện luồng cũng cung cấp các chức năng đầu vào và đầu ra được định dạng mạnh mẽ (printf và scanf) cũng như các chức năng cho đầu vào và đầu ra hướng ký tự và dòng.
Vì các luồng được triển khai dưới dạng bộ mô tả tệp, bạn có thể trích xuất bộ mô tả tệp từ một luồng và thực hiện các hoạt động cấp thấp trực tiếp trên bộ mô tả tệp. Ban đầu, bạn cũng có thể mở một kết nối làm trình mô tả tệp và sau đó tạo một luồng được liên kết với trình mô tả tệp đó.
Nói chung, bạn nên gắn bó với việc sử dụng các luồng hơn là bộ mô tả tệp, trừ khi có một số thao tác cụ thể mà bạn muốn thực hiện mà chỉ có thể được thực hiện trên bộ mô tả tệp. Nếu bạn là một lập trình viên mới bắt đầu và không chắc chắn nên sử dụng các chức năng nào, chúng tôi khuyên bạn nên tập trung vào các chức năng đầu vào được định dạng (xem Đầu vào có định dạng) và các chức năng đầu ra được định dạng (xem Đầu ra có định dạng).
Nếu bạn lo lắng về tính khả chuyển của các chương trình của mình với các hệ thống khác ngoài GNU, bạn cũng nên biết rằng các bộ mô tả tệp không di động như các luồng. Bạn có thể mong đợi bất kỳ hệ thống nào chạy ISO C hỗ trợ các luồng, nhưng các hệ thống không phải GNU có thể không hỗ trợ bộ mô tả tệp, hoặc chỉ có thể triển khai một tập hợp con của các hàm GNU hoạt động trên bộ mô tả tệp. Tuy nhiên, hầu hết các chức năng của bộ mô tả tệp trong Thư viện GNU C đều có trong tiêu chuẩn POSIX.1.