C fopen vs open


219

Чи є якась причина (крім синтаксичної), яку ви хочете використовувати

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?


Ви мали на увазі fdopenі openчи fopenі і open?
user7116

Ви не маєте на увазі fopen, не fdopen?
всезнайко

9
fopenє частиною стандартної бібліотеки С, openні. Використовувати fopenпри написанні портативного коду.
Азіз

Так, я мав на увазі фопен. Я просто оновив його, але, думаю, застосовується той самий принцип.
LJM

6
@Aziz, openє функцією POSIX.
dreamlax

Відповіді:


243

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

Існує чотири основні причини використовувати fopenзамість open.

  1. fopenнадає вам буферний IO, який може виявитися набагато швидшим, ніж те, що ви робите open.
  2. fopen робить переклад, що закінчується трансляцією, якщо файл не відкрито у двійковому режимі, що може бути дуже корисно, якщо ваша програма коли-небудь переноситься в не-Unix-середовище (хоча світ, схоже, конвергується лише на LF (за винятком текстових мереж на основі IETF) протоколи типу SMTP і HTTP і подібні)).
  3. A FILE *дає можливість використовувати fscanfта інші функції stdio.
  4. Ваш код може колись потрібно перенести на якусь іншу платформу, яка підтримує лише ANSI C і не підтримує цю openфункцію.

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

І більшість платформ, які підтримують C, мають openфункцію.

Це залишає питання буферизації. У місцях, де ви в основному читаєте або записуєте файл послідовно, підтримка буферизації є дуже корисною та значною швидкістю. Але це може призвести до деяких цікавих проблем, коли дані не закінчуються у файлі, коли ви очікуєте їх наявності. Ви повинні пам’ятати про це fcloseабо fflushу відповідний час

Якщо ви займаєтеся прагненнями (ака fsetposабо fseekдругий з них трохи складніше використовувати у відповідності зі стандартами), корисність буферизації швидко знижується.

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


4
Я не збираюся сумніватися у ваших переживаннях, але я хотів би почути, як ви трохи деталізуєте це. Для яких програм ви вважаєте, що вбудована буферизація стає на шляху? У чому саме проблема?
Еміль Н

1
Не бачив останнього абзацу. Дійсна точка, ІМХО. Наскільки я можу сказати, питання стосувалося IO файлів.
Еміль Н

7
Щоб уточнити, коли буферизація заважає. Це коли ви використовуєте пошук. Наступне читання з будь-якою командою ( fgets, fgetc, fscanf, fread), завжди буде читати весь розмір буфера (4K, 8K або як ви встановите). Використовуючи прямий ввід / вивід, ви можете цього уникнути. У цьому випадку ще краще використовувати preadзамість пари "шукати / читати" (1 sscall замість 2).
Патрік Шлютер

2
Робота з перервами read()та write()викликами є зручною п'ятою причиною використання сімейства функцій libc.
nccc

3
@ m-ric: Ну, це дещо не пов'язане питання, але так. Усі платформи, що підтримують, ioctlтакож підтримують filenoдзвінок, який приймає a FILE *і повертає номер, який може бути використаний у ioctlвиклику. Будьте обережні, хоча. FILE *пов'язані дзвінки можуть несподівано взаємодіяти з використанням, ioctlщоб змінити щось про дескриптор базового файлу.
всезначний

53

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

Є кілька переваг використання FILE-об'єктів, а не сирих дескрипторів файлів, що включає більшу простоту використання, але й інші технічні переваги, такі як вбудована буферизація. Особливо буферизація, як правило, призводить до значної переваги продуктивності.


3
Чи є якісь недоліки у використанні захищеної версії 'f ...'?
LJM

5
@L. Moser, так, коли ви вже буферуєте дані, а отже, додатковий буфер додає зайві копіювання та накладні витрати.
Michael Aaron Safyan

6
насправді є й інші недоліки. fopen()не забезпечує однаковий рівень контролю при відкритті файлів, наприклад, створення дозволів, режимів спільного використання тощо. Зазвичай open()і варіанти забезпечують набагато більший контроль, близький до того, що насправді забезпечує операційна система
Matt Joiner

2
Існують також крайні випадки, коли ви mmapфайл і вносити зміни за допомогою нормального вводу / виводу (настільки ж неймовірне, як це здається, ми робимо насправді, що в нашому проекті і з реальних обґрунтованих причин) буферизація буде заважати.
Патрік Шлютер

Ви також можете використовувати інші системні функції, наприклад, використовувати open () для попередньої завантаження файлів у кеш сторінки за допомогою readahead (). Я думаю, що правило: "використовувати fopen, якщо вам абсолютно не потрібно open ()";
Томаш Прузіна

34

fopen vs open у С

1) fopen- це функція бібліотеки, тоді openяк системний виклик .

2) fopenзабезпечує буферний введення - висновок , який швидше , по порівнянні з openяким це НЕ буферизацией .

3) fopenє портативним , а openНЕ портативним ( відкритим є середовище конкретним ).

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

5) A FILE *дає вам можливість використовувати fscanf та інші функції stdio.


9
openє стандартом POSIX, тому він досить портативний
osvein

12

Якщо ви не входите до 0,1% застосунків, де використання openфактичної переваги від продуктивності, насправді немає вагомих причин не використовувати fopen. Що fdopenстосується того, якщо ви не граєте з дескрипторами файлів, цей дзвінок вам не потрібен.

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


11

Якщо у вас є FILE *, ви можете використовувати такі функції , як fscanf, fprintfі fgetsт.д. Якщо у вас є тільки дескриптор файлу, ви обмежені (але , ймовірно , швидше) підпрограми введення і виведення read, і writeт.д.


7

Використання відкритого читання, запису означає, що вам доведеться турбуватися про взаємодію сигналів.

Якщо виклик був перерваний обробником сигналу, функції повернуться -1 і встановлять errno на EINTR.

Тож правильним способом було б закрити файл

while (retval = close(fd), retval == -1 && ernno == EINTR) ;

4
Бо closeце залежить від операційної системи. Неправильно робити цикл для Linux, AIX та деяких інших операційних систем.
strcat

Крім того, використання читання і запису постраждає від тієї ж проблеми, тобто вони можуть перерватися сигналом перед тим, як повністю обробити вхід / висновок, і програміст повинен впоратися з такими ситуаціями, в той час як фрейд і fwrite керують перебоями сигналу.
Марсело

6

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

У Unix:
Ви можете отримати вказівник на файл з дескриптора файлів, використовуючи:

fP = fdopen(fD, "a");

Ви можете отримати дескриптор файлу з файлового вказівника, використовуючи:

fD = fileno (fP);

4

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


2

Я змінив на open () з fopen () для моєї програми, оскільки fopen викликав подвійне читання кожного разу, коли я запускав fopen fgetc. Подвійні читання були руйнівними для того, що я намагався досягти. open (), здається, робить те, що ви просите.


2

Залежить також від того, які прапори потрібно відкрити. Що стосується використання для запису та читання (і переносимості), слід використовувати f *, як було зазначено вище.

Але якщо в основному ви хочете вказати більше, ніж стандартні прапори (наприклад, rw та додавати прапорці), вам доведеться використовувати API для платформи (наприклад, POSIX open) або бібліотеку, яка резюмує ці деталі. C-стандарт не має таких прапорів.

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

Наприклад, в системах Linux є світлодіодний інтерфейс, відкритий через sysfs. Він відкриває яскравість світлодіода через файл. Написання чи читання числа у вигляді рядка від 0-255. Звичайно, ви не хочете створювати цей файл, а писати в нього лише тоді, коли він існує. Класна річ: Використовуйте fdopen для читання / запису цього файлу, використовуючи стандартні дзвінки.


0

відкривши файл за допомогою 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?
obayhan

так, відкритим є системний виклик, який швидше, ніж fopen - порівняльно @obayhan
prashad
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.