Ответы:
Дескриптор файла - это низкоуровневый целочисленный «дескриптор», используемый для идентификации открытого файла (или сокета, или чего-то еще) на уровне ядра в Linux и других Unix-подобных системах.
Вы передаете "голые" файловые дескрипторы в фактические вызовы Unix, например read()
,write()
и так далее.
FILE
Указатель представляет собой стандартную библиотеку уровня конструкт C, используемый для представления файла. FILE
Обертывания дескриптор файла, и добавляет буферизацию и другие функции , чтобы сделать / O проще я.
Вы передаете FILE
указатели на стандартные функции C, такие как fread()
и fwrite()
.
fd
это первый аргумент read()
. Почему вы называете это голым?
FILE *
типом стандартной библиотеки , целочисленный файловый дескриптор "менее обернут", то есть "голый".
Один буферизован ( FILE *
), а другой нет. На практике вы хотите использоватьFILE *
почти всегда, когда читаете из «реального» файла (то есть на диске), если вы не знаете, что делаете, или если ваш файл на самом деле не является сокетом или около того ..
Вы можете получить дескриптор файла из FILE *
использования, fileno()
и вы можете открыть буферизованный FILE *
из дескриптора файла, используяfdopen()
Дескриптор файла - это просто целое число, которое вы получаете в результате open()
вызова POSIX . Используя стандартный C, fopen()
вы получаете FILE
структуру обратно. Структура FILE
содержит этот файловый дескриптор, среди прочего, например, индикатор конца файла и ошибки, позицию потока и т. Д.
Таким образом, использование fopen()
дает вам определенную абстракцию по сравнению с open()
. В общем, вам следует использовать, fopen()
поскольку это более переносимо, и вы можете использовать все другие стандартные функции C, которые используют FILE
структуру, т. Е.fprintf()
И семейство.
Нет никаких проблем с производительностью при использовании.
Дескриптор файла против указателя файла
Дескриптор файла:
Дескриптор файла - это целое число, возвращаемое open()
системным вызовом.
int fd = open (filePath, mode);
Указатель файла:
Указатель файла - это указатель на структуру C, возвращаемую fopen()
библиотечной функцией, которая используется для идентификации файла, упаковки дескриптора файла, функций буферизации и всех других функций, необходимых для операции ввода-вывода . Указатель файла имеет тип FILE , определение которого можно найти в "/usr/include/stdio.h" . Это определение может варьироваться от одного компилятора к другому.
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;
Хотите добавить точки, которые могут быть полезны.
ОКОЛО FILE *
Я много раз использую его для журналов отладки. пример,
FILE *fp;
fp = fopen("debug.txt","a");
fprintf(fp,"I have reached till this point");
fclose(fp);
ОКОЛО FILE DESCRIPTOR
Обычно он используется для IPC.
Предоставляет низкоуровневый контроль над файлами в системах * nix (устройства, файлы, сокеты и т. Д.), Следовательно, более мощный, чем FILE *
.
fdopen()
такие вещи, как IPC и устройства FILE*
?
FILE*
, но вы можете создать FILE*
из файлового дескриптора ( fdopen()
), а затем FILE
закрыть дескриптор. Таким образом, вы можете сделать IPC, но вам приходится иметь дело с дескрипторами файлов немного , чтобы облегчить любой прямой IPC.
FILE *
является более полезным при работе с текстовыми файлами и пользовательским вводом / выводом, поскольку он позволяет использовать функции API , как sprintf()
, sscanf()
, fgets()
, и feof()
т.д.
API файловых дескрипторов является низкоуровневым, поэтому он позволяет работать с сокетами, каналами, отображенными в память файлами (и, конечно, с обычными файлами).
Просто заметка, чтобы завершить обсуждение (если интересно) ....
fopen
может быть небезопасным, и вам, вероятно, следует использовать fopen_s
или open
с установленными эксклюзивными битами. C1X предлагает x
режимы, так что вы можете fopen
с режимами "rx"
,"wx"
и т.д.
Если вы используете open
, вы можете рассмотреть open(..., O_EXCL | O_RDONLY,... )
илиopen(..., O_CREAT | O_EXCL | O_WRONLY,... )
.
См., Например, « Не делайте предположений относительно fopen () и создания файлов» .
fopen_s
, кажется, недоступен POSIX
, я предполагаю, что наиболее переносимым вариантом будет to open(2)
and then fdopen(2)
. (оставляя окна в стороне). Кроме того, что будет быстрее fopen_s()
или open(2)
за чем последует fdopen(2)
?
Системные вызовы в основном используют файловый дескриптор, например read
и write
. Библиотечная функция будет использовать указатели файлов ( printf
, scanf
). Но библиотечные функции используют только внутренние системные вызовы.
Я нашел хороший ресурс здесь , что дает подробный обзор различий между ними:
Когда вы хотите выполнить ввод или вывод в файл, у вас есть выбор из двух основных механизмов для представления связи между вашей программой и файлом: дескрипторы файлов и потоки. Дескрипторы файлов представлены как объекты типа int, а потоки представлены как объекты FILE *.
Дескрипторы файлов обеспечивают примитивный низкоуровневый интерфейс для операций ввода и вывода. И дескрипторы файлов, и потоки могут представлять соединение с устройством (например, терминалом), канал или сокет для связи с другим процессом, а также обычный файл. Но если вы хотите выполнять управляющие операции, специфичные для определенного типа устройства, вы должны использовать файловый дескриптор; нет возможности использовать потоки таким образом. Вы также должны использовать файловые дескрипторы, если ваша программа должна выполнять ввод или вывод в специальных режимах, таких как неблокирующий (или опрашиваемый) ввод (см. Флаги состояния файла).
Потоки предоставляют интерфейс более высокого уровня, расположенный поверх примитивных средств дескриптора файла. Интерфейс потока обрабатывает все типы файлов практически одинаково - единственное исключение составляют три стиля буферизации, которые вы можете выбрать (см. Буферизация потока).
Основное преимущество использования потокового интерфейса состоит в том, что набор функций для выполнения фактических операций ввода и вывода (в отличие от операций управления) над потоками намного богаче и мощнее, чем соответствующие средства для файловых дескрипторов. Интерфейс файлового дескриптора предоставляет только простые функции для передачи блоков символов, но потоковый интерфейс также предоставляет мощные функции форматированного ввода и вывода (printf и scanf), а также функции для символьного и строчно-ориентированного ввода и вывода.
Поскольку потоки реализованы в терминах файловых дескрипторов, вы можете извлечь файловый дескриптор из потока и выполнять низкоуровневые операции непосредственно с файловым дескриптором. Вы также можете сначала открыть соединение как файловый дескриптор, а затем создать поток, связанный с этим файловым дескриптором.
В общем, вы должны придерживаться использования потоков, а не файловых дескрипторов, если нет какой-либо конкретной операции, которую вы хотите сделать, которая может быть выполнена только с файловым дескриптором. Если вы начинающий программист и не знаете, какие функции использовать, мы предлагаем вам сконцентрироваться на функциях форматированного ввода (см. Форматированный ввод) и функциях форматированного вывода (см. Форматированный вывод).
Если вас беспокоит переносимость ваших программ в системы, отличные от GNU, вы также должны знать, что файловые дескрипторы не так переносимы, как потоки. Вы можете ожидать, что любая система, работающая под управлением ISO C, будет поддерживать потоки, но системы, не относящиеся к GNU, могут вообще не поддерживать файловые дескрипторы или могут реализовывать только подмножество функций GNU, которые работают с файловыми дескрипторами. Однако большинство функций файловых дескрипторов в библиотеке GNU C включены в стандарт POSIX.1.