Sự khác biệt giữa bộ mô tả tệp và con trỏ tệp là gì?


Câu trả lời:


144

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 FILEtrỏ 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 FILEbao 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 FILEcon trỏ đến các hàm C tiêu chuẩn chẳng hạn như fread()fwrite().


@nvl: fildes chắc chắn có sẵn cho Windows, ví dụ: msdn.microsoft.com/en-us/library/z0kc8e3z%28VS.80%29.aspx
kennytm

2
@unwind Ý bạn là gì về bộ mô tả tệp "trần trụi"? Tham chiếu được liên kết cho biết rằng fdlà đối số đầu tiên read(). Tại sao bạn gọi nó là khỏa thân?
Geek

3
@Geek So với 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".
thư giãn

57

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()


12
+1 để chỉ ra fileno (), việc tổ chức các trang nam khiến trang này khó tìm. Tương tự cho fdopen ().
BD tại Rivenhill

20

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 FILEcấu trúc trở lại. Cấu FILEtrú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 FILEstruct, tức là fprintf()và family.

Không có vấn đề về hiệu suất khi sử dụng.


8
+1 để nâng cao tính di động. FILE là một phần của Thư viện C Chuẩn (trở lại C89 / C90); bộ mô tả tệp không phải.
tomlogic

15

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);

  1. Trình xử lý cấp độ hạt nhân / thấp.
  2. chuyển sang đọc () và ghi () các Lệnh gọi Hệ thống UNIX.
  3. Không bao gồm bộ đệm và các tính năng như vậy.
  4. Ít di động và thiếu hiệu quả.

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;
  1. Đó là giao diện cấp cao.
  2. Được truyền cho các hàm fread () và fwrite ().
  3. Bao gồm bộ đệm, chỉ báo lỗi và phát hiện EOF, v.v.
  4. Mang lại tính di động và hiệu quả cao hơn.

1
Bạn có thể sao lưu tuyên bố hiệu quả cao hơn đó không? Tôi chưa bao giờ nghe điều đó.
Gid

1
Yêu cầu "hiệu quả" có thể là do bộ đệm. Với bộ mô tả tệp, mọi read () hoặc write () là một syscall và mọi syscall nên được coi là đắt tiền. Với FILE *, việc lưu vào bộ đệm có nghĩa là một số lần đọc và ghi sẽ không phải là cuộc gọi tổng hợp.
Mike Spear

12

Muốn thêm điểm có thể hữu ích.

TRONG KHOẢNG FILE *

  1. không thể được sử dụng cho giao tiếp giữa các quá trình (IPC).
  2. sử dụng nó khi bạn cần I / O được đệm mục đích chung. (printf, frpintf, snprintf, scanf)
  3. 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

  1. Nó thường được sử dụng cho IPC.

  2. 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 *.


Bạn không thể sử dụng fdopen() để làm những việc như IPC và các thiết bị với FILE*?
osvein

Trên thực tế, cả có và không. Bạn không thể thiết lập và khởi tạo IPC với 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 FILEcũ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.
Micah W

3

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).


1
+1 vì bạn đã thêm tệp ánh xạ bộ nhớ, kể từ lần đọc hiện tại của tôi, các câu trả lời khác đã được cung cấp.
ernie.cordell

3

Chỉ cần một ghi chú để kết thúc cuộc thảo luận (nếu quan tâm) ....

fopencó thể không an toàn và bạn có thể nên sử dụng fopen_shoặc openvới bộ bit độc quyền. C1X đang cung cấp xcác chế độ, vì vậy bạn có thể fopenvớ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 .


Như fopen_sdườ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ì?
Mihir

1

Ví dụ: các cuộc gọi hệ thống chủ yếu sử dụng bộ mô tả tệp readwrite. 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 không chắc tại sao bạn lại nói rằng các hàm thư viện chỉ sử dụng lệnh gọi hệ thống nội bộ: Nếu bạn muốn nói đến các hàm CI / O tiêu chuẩn (hoặc bất kỳ hàm nào khác cho vấn đề đó), tôi không chắc điều đó (phổ biến?) Đúng. Nếu không, đó không phải là những gì bạn đã nói, vì vậy tôi muốn thấy ngôn ngữ trong bài đăng của bạn được làm sạch một chút. Câu cuối cùng làm tôi bối rối.
ernie.cordell

1

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.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.