C fopen vs open - PullRequest
       40

C fopen vs open

194 голосов
/ 02 ноября 2009

Есть ли какая-либо причина (кроме синтаксической), которую вы хотите использовать

FILE *fdopen(int fd, const char *mode);

или

FILE *fopen(const char *path, const char *mode);

вместо

int open(const char *pathname, int flags, mode_t mode);

при использовании C в среде Linux?

Ответы [ 11 ]

223 голосов
/ 02 ноября 2009

Во-первых, нет особой причины использовать fdopen, если fopen является опцией, а open - другой возможный выбор. Вы не должны были использовать open, чтобы открыть файл, если вы хотите FILE *. Поэтому включение fdopen в этот список неверно и сбивает с толку, потому что оно не очень похоже на другие. Теперь я перейду к его игнорированию, потому что здесь важно различать стандарт C FILE * и дескриптор файла для конкретной ОС.

Существует четыре основных причины использовать fopen вместо open.

  1. fopen обеспечивает вам буферизацию ввода-вывода, которая может оказаться намного быстрее, чем то, что вы делаете с open.
  2. fopen выполняет перевод конца строки, если файл не открывается в двоичном режиме, что может быть очень полезно, если ваша программа портирована в не-Unix-среду.
  3. A FILE * дает вам возможность использовать fscanf и другие функции stdio.
  4. Возможно, когда-нибудь ваш код придется перенести на другую платформу, которая поддерживает только ANSI C и не поддерживает функцию open.

По моему мнению, перевод конца строки чаще встречается на вашем пути, чем помогает, а синтаксический анализ fscanf настолько слаб, что вы неизбежно в конечном итоге выбрасываете его в пользу чего-то более полезного.

И большинство платформ, поддерживающих C, имеют функцию open.

Это оставляет вопрос буферизации. В местах, где вы в основном читаете или пишете файл последовательно, поддержка буферизации действительно полезна и значительно повышает скорость. Но это может привести к некоторым интересным проблемам, при которых данные не попадают в файл, когда вы ожидаете, что они там будут. Вы должны помнить fclose или fflush в соответствующее время.

Если вы выполняете поиск (или fsetpos или fseek, второй из которых немного сложнее использовать в соответствии со стандартами), полезность буферизации быстро снижается.

Конечно, мой уклон заключается в том, что я склонен много работать с сокетами, и есть тот факт, что вы действительно хотите делать неблокирующий ввод-вывод (который FILE * полностью не поддерживает каким-либо разумным способом) с нет никакой буферизации и часто сложные требования синтаксического анализа действительно окрашивают мое восприятие.

47 голосов
/ 02 ноября 2009

open() - это вызов низкого уровня. fdopen() преобразует файловый дескриптор уровня os в высокоуровневую FILE-абстракцию языка C. fopen() вызывает open() в фоновом режиме и дает вам FILE-указатель напрямую.

Существует несколько преимуществ использования объектов FILE, а не сырых файловых дескрипторов, что включает в себя большую простоту использования, но также и другие технические преимущества, такие как встроенная буферизация. В частности, буферизация обычно дает значительное преимущество в производительности.

27 голосов
/ 26 ноября 2015

открытие против открытия в C

1) fopen - это библиотечная функция , в то время как open - это системный вызов .

2) fopen обеспечивает буферизованный ввод-вывод , который быстрее по сравнению с open, который не буферизован .

3) fopen является переносным , в то время как open не переносным ( открыто для конкретной среды ).

4) fopen возвращает указатель на структуру FILE (FILE *) ; open возвращает целое число, идентифицирующее файл.

5) FILE * дает вам возможность использовать fscanf и другие функции stdio.

11 голосов
/ 02 ноября 2009

Если у вас есть FILE *, вы можете использовать такие функции, как fscanf, fprintf и fgets и т. Д. Если у вас есть только дескриптор файла, у вас есть ограниченные (но, вероятно, более быстрые) процедуры ввода и вывода read, write и т. Д.

10 голосов
/ 02 ноября 2009

Если вы не являетесь частью 0,1% приложений, в которых использование open является фактическим выигрышем в производительности, на самом деле нет веской причины не использовать fopen. Что касается fdopen, если вы не играете с файловыми дескрипторами, вам не нужен этот вызов.

Придерживайтесь fopen и его семейства методов (fwrite, fread, fprintf и др.), И вы останетесь очень довольны. Не менее важно, что другие программисты останутся довольны вашим кодом.

7 голосов
/ 05 мая 2010

Использование open, read, write означает, что вам нужно беспокоиться о сигнальных взаимодействиях.

Если вызов был прерван обработчиком сигнала, функции вернут -1 и установите errno на EINTR.

Таким образом, правильный способ закрыть файл будет

while (retval = close(fd), retval == -1 && ernno == EINTR) ;
4 голосов
/ 09 января 2015

open () будет вызываться в конце каждой из функций семейства fopen () . open () - системный вызов, а fopen () предоставляются библиотеками в качестве функций-оболочек для простоты использования.

4 голосов
/ 09 января 2015

open() - системный вызов, специфичный для Unix-систем, и он возвращает дескриптор файла. Вы можете записать в дескриптор файла, используя write(), который является другим системным вызовом.
fopen() - это вызов функции ANSI C, который возвращает указатель на файл и переносим для других ОС. Мы можем записать в указатель файла, используя fprintf.

В Unix:
Вы можете получить указатель файла из дескриптора файла, используя:

fP = fdopen(fD, "a");

Вы можете получить дескриптор файла из указателя файла, используя:

fD = fileno (fP);
2 голосов
/ 11 марта 2016

Зависит также от того, какие флаги требуется открыть. В отношении использования для записи и чтения (и переносимости) следует использовать f *, как указано выше.

Но если в основном вы хотите указать больше, чем стандартные флаги (например, rw и append flags), вам придется использовать API для конкретной платформы (например, POSIX open) или библиотеку, которая абстрагирует эти детали. Стандарт C не имеет таких флагов.

Например, вы можете открыть файл, только если он завершится. Если вы не укажете флаг создания, файл должен существовать. Если вы добавите эксклюзив для создания, он будет создавать файл, только если он не существует. Есть еще много.

Например, в системах Linux есть светодиодный интерфейс, доступный через sysfs. Это выставляет яркость ведомого через файл. Запись или чтение числа в виде строки в диапазоне от 0 до 255. Конечно, вы не хотите создавать этот файл и записывать его, только если он существует. Самое интересное: используйте fdopen для чтения / записи этого файла, используя стандартные вызовы.

1 голос
/ 03 апреля 2012

Я переключился на open () из fopen () для моего приложения, потому что fopen вызывал двойное чтение каждый раз, когда я запускал fopen fgetc. Двойное чтение разрушило то, что я пытался достичь. open () просто делает то, о чем вы просите.

...