C fopen vs open

172

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

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?

  • 0
    Вы fdopen виду fdopen и open или fopen и open ?
  • 0
    Разве вы не имеете в виду fopen, а не fdopen?
Показать ещё 5 комментариев
Теги:
file-io
fopen

11 ответов

206
Лучший ответ

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

Есть четыре основные причины использовать fopen вместо open.

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

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

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

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

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

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

  • 4
    Я не собираюсь ставить под сомнение ваш опыт, но я бы хотел услышать, что вы немного подробнее остановитесь на этом. Как вы считаете, для каких приложений мешает встроенная буферизация? в чем именно проблема?:
  • 0
    Не видел последний абзац. Допустимая точка, ИМХО. Насколько я могу судить, вопрос был о IO файла, хотя.
Показать ещё 11 комментариев
44

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

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

  • 3
    Есть ли недостатки в использовании буферизованных версий 'f ...' open?
  • 5
    @L. Мозер, да, когда вы уже буферизуете данные, и, следовательно, дополнительный буфер добавляет ненужное копирование и накладные расходы памяти.
Показать ещё 3 комментария
24

fopen vs open в C

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

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

3) fopen переносимый, а open не переносимый (open - это специфический для среды).

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

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

  • 4
    open это стандарт POSIX, так что он довольно переносимый
11

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

10

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

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

7

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

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

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

while (retval = close(fd), retval == -1 && ernno == EINTR) ;
  • 4
    Для close это зависит от операционной системы. Неправильно выполнять цикл в Linux, AIX и некоторых других операционных системах.
  • 0
    Кроме того, использование чтения и записи будет страдать от одной и той же проблемы, то есть они могут быть прерваны сигналом перед полной обработкой ввода / вывода, и программист должен справиться с такими ситуациями, в то время как fread и fwrite хорошо обрабатывают прерывания сигнала.
4

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

4

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

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

fP = fdopen(fD, "a");

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

fD = fileno (fP);
2

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

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

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

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

1

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

-1

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

1.firstly it searches on the disk the file to be opened.
2.then it loads the file from the disk into a place in memory called buffer.
3.it sets up a character pointer that points to the first character of the buffer.

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

  • 0
    открыт быстрее чем fopen?
  • 0
    да, open это системный вызов, который быстрее, чем fopen - сравнительно @obayhan

Ещё вопросы

Сообщество Overcoder
Наверх
Меню