C fopen vs open

219

Gibt es einen anderen Grund (als syntaktische), den Sie verwenden möchten?

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

oder

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

anstatt

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

bei Verwendung von C in einer Linux-Umgebung?

LJM
quelle
Meinten Sie fdopenund openoder fopenund und open?
user7116
Meinst du nicht fopen, nicht fdopen?
Omnifarious
9
fopenist Teil der Standard-C-Bibliothek, opennicht. Verwenden Sie diese Option, fopenwenn Sie tragbaren Code schreiben.
Aziz
Ja, ich meinte offen. Ich habe es gerade aktualisiert, aber ich denke, dass das gleiche Prinzip gilt.
LJM
6
@ Aziz, openist allerdings eine POSIX-Funktion.
Dreamlax

Antworten:

242

Erstens gibt es keinen besonders guten Grund, fdopenwenn dies fopeneine Option und opendie andere mögliche Wahl ist. Sie hätten opendie Datei gar nicht erst öffnen sollen, wenn Sie eine möchten FILE *. Die Aufnahme fdopenin diese Liste ist also falsch und verwirrend, da sie den anderen nicht sehr ähnlich ist. Ich werde es jetzt ignorieren, da hier ein wichtiger Unterschied zwischen einem C-Standard bestehtFILE * und einem betriebssystemspezifischen Dateideskriptor besteht.

Es gibt vier Hauptgründe, fopenanstatt zu verwenden open.

  1. fopen bietet Ihnen Puffer-E / A, die sich als viel schneller herausstellen können als das, was Sie tun open .
  2. fopen führt eine Zeilenendübersetzung durch, wenn die Datei nicht im Binärmodus geöffnet ist. Dies kann sehr hilfreich sein, wenn Ihr Programm jemals in eine Nicht-Unix-Umgebung portiert wurde (obwohl die Welt scheinbar nur auf LF konvergiert (außer auf IETF-Text-basiertem Netzwerk) Protokolle wie SMTP und HTTP und so)).
  3. A FILE *gibt Ihnen die Möglichkeit zu verwendenfscanf und andere Standardfunktionen zu verwenden.
  4. Möglicherweise muss Ihr Code eines Tages auf eine andere Plattform portiert werden, die nur ANSI C unterstützt und die openFunktion nicht unterstützt .

Meiner Meinung nach steht Ihnen die Übersetzung am Ende der Zeile häufiger im Weg als hilft Ihnen und das Parsen von fscanf ist so schwach, dass Sie es unweigerlich zugunsten von etwas Nützlicherem wegwerfen.

Und die meisten Plattformen, die C unterstützen, haben eine open Funktion.

Damit bleibt die Pufferfrage. An Orten, an denen Sie eine Datei hauptsächlich nacheinander lesen oder schreiben, ist die Pufferunterstützung sehr hilfreich und eine große Geschwindigkeitsverbesserung. Es kann jedoch zu interessanten Problemen kommen, bei denen Daten nicht in der Datei landen, wenn Sie erwarten, dass sie dort vorhanden sind. Sie müssen sich an fcloseoder erinnernfflush zu den richtigen Zeiten .

Wenn Sie suchen (aka fsetposoderfseek die zweite ist etwas schwieriger, standardkonform zu verwenden), nimmt der Nutzen der Pufferung schnell ab.

Natürlich ist meine Tendenz, dass ich dazu neige, viel mit Sockets zu arbeiten, und da die Tatsache, dass Sie wirklich nicht blockierende E / A-Vorgänge (die FILE *in keiner vernünftigen Weise vollständig unterstützt werden) ohne Pufferung und häufig ausführen möchten Komplexe Parsing-Anforderungen haben meine Wahrnehmung wirklich beeinflusst.

Allgegenwärtig
quelle
4
Ich werde Ihre Erfahrungen nicht in Frage stellen, aber ich würde gerne hören, wie Sie dies etwas näher erläutern. Für welche Art von Anwendungen steht Ihrer Meinung nach die integrierte Pufferung im Weg? Was genau ist das Problem?
Emil H
1
Ich habe den letzten Absatz nicht gesehen. Gültiger Punkt, IMHO. Soweit ich das beurteilen kann, handelte es sich bei der Frage jedoch um Datei-E / A.
Emil H
7
Um zu klären, wann die Pufferung im Weg ist. Es ist, wenn Sie suchen verwenden. Die folgende Lese mit dem, was Befehl ( fgets, fgetc, fscanf, fread), liest immer die ganze Größe des Puffers (4K, 8K oder was auch immer Sie setzen). Durch die Verwendung der direkten E / A können Sie dies vermeiden. In diesem Fall ist es sogar noch besser, preadanstelle eines Such- / Lesepaars (1 Syscall anstelle von 2) zu verwenden.
Patrick Schlüter
2
Die Behandlung von Unterbrechungen read()und write()Aufrufen ist ein bequemer fünfter Grund, die libc-Funktionsfamilie zu verwenden.
NCCC
3
@ m-ric: Nun, das ist eine etwas unabhängige Frage, aber ja. Alle Plattformen, die unterstützen, unterstützen ioctlauch diefileno Anruf, der FILE *eine Nummer annimmt und zurückgibt, die in einem ioctlAnruf verwendet werden kann. Sei aber vorsichtig. FILE *Verwandte Aufrufe können überraschend mit der Verwendung interagieren ioctl, um etwas am zugrunde liegenden Dateideskriptor zu ändern.
Omnifarious
53

open()ist ein Low-Level-OS-Aufruf. fdopen()konvertiert einen Dateideskriptor auf Betriebssystemebene in die übergeordnete FILE-Abstraktion der C-Sprache. fopen()ruft open()im Hintergrund auf und gibt Ihnen direkt einen DATEI-Zeiger.

Die Verwendung von FILE-Objekten anstelle von Rohdateideskriptoren bietet mehrere Vorteile. Dazu gehören eine einfachere Verwendung, aber auch andere technische Vorteile wie die integrierte Pufferung. Insbesondere die Pufferung führt im Allgemeinen zu einem beträchtlichen Leistungsvorteil.

Emil H.
quelle
3
Gibt es irgendwelche Nachteile bei der Verwendung der gepufferten 'f ...' - Versionen von open?
LJM
5
@L. Moser, ja, wenn Sie die Daten bereits puffern und der zusätzliche Puffer unnötigen Kopier- und Speicheraufwand verursacht.
Michael Aaron Safyan
6
Eigentlich gibt es noch andere Nachteile. fopen()bietet nicht die gleiche Kontrolle beim Öffnen von Dateien, z. B. Erstellen von Berechtigungen, Freigabemodi und mehr. Typischerweise open()und Varianten bieten viel mehr Kontrolle, nahe an dem, was das Betriebssystem tatsächlich bietet
Matt Joiner
2
Es gibt auch extreme Fälle, in denen Sie mmapdie Datei ändern und mit normaler E / A Änderungen vornehmen (so unglaublich es auch klingt, dass wir dies in unserem Projekt und aus wirklich guten Gründen tun), die Pufferung würde im Weg stehen.
Patrick Schlüter
Möglicherweise möchten Sie auch andere Systemfunktionen verwenden, z. B. open () zum Vorladen von Dateien in den Seitencache über readahead (). Ich denke, die Faustregel lautet "benutze fopen, es sei denn, du brauchst unbedingt open ()". Mit open () kannst du tatsächlich ausgefallene Dinge tun (O_ATIME einstellen und nicht einstellen und ähnliches).
Tomas Pruzina
34

fopen vs open in C.

1) fopenist eine Bibliotheksfunktion, während openes sich um einen Systemaufruf handelt .

2) fopenliefert gepufferte E / A, die schneller openist als nicht gepufferte .

3) fopenist tragbar , während opennicht tragbar ( offen ist umgebungsspezifische ).

4) fopengibt einen Zeiger auf eine FILE-Struktur zurück (FILE *) ; openGibt eine Ganzzahl zurück, die die Datei identifiziert.

5) A FILE *gibt Ihnen die Möglichkeit, fscanf und andere stdio-Funktionen zu verwenden.

Yogeesh HT
quelle
9
openist ein POSIX-Standard, also ziemlich portabel
osvein
12

Wenn Sie nicht zu 0,1% der Anwendungen gehören, bei denen die Verwendung openeinen tatsächlichen Leistungsvorteil darstellt, gibt es keinen guten Grund, sie nicht zu verwenden fopen. Soweit fdopengeht, wenn Sie nicht mit Filedeskriptoren spielen, müssen Sie nicht diesen Anruf.

Stick mit fopenund seine Familie von Methoden ( fwrite, fread, fprintf, et al) , und Sie werden sehr zufrieden sein. Ebenso wichtig ist, dass andere Programmierer mit Ihrem Code zufrieden sind.

user7116
quelle
11

Wenn Sie eine haben FILE *, können Sie Funktionen wie fscanf, fprintfund fgetsetc. Wenn Sie nur den Dateideskriptor haben, haben Sie begrenzt (aber wahrscheinlich schneller) Ein- und Ausgaberoutinen read, writeusw.

Dreamlax
quelle
7

Wenn Sie Öffnen, Lesen und Schreiben verwenden, müssen Sie sich um Signalinteraptionen kümmern.

Wenn der Anruf von einem Signalhandler unterbrochen wurde, geben die Funktionen -1 zurück und setzen errno auf EINTR.

Der richtige Weg, um eine Datei zu schließen, wäre also

while (retval = close(fd), retval == -1 && ernno == EINTR) ;
digy
quelle
4
Für closehängt dies vom Betriebssystem ab . Es ist falsch, die Schleife unter Linux, AIX und einigen anderen Betriebssystemen durchzuführen.
Strcat
Darüber hinaus tritt bei der Verwendung von Lesen und Schreiben das gleiche Problem auf, dh sie können durch ein Signal unterbrochen werden, bevor die Ein- / Ausgabe vollständig verarbeitet wird, und der Programmierer muss mit solchen Situationen umgehen, während Fread und Fwrite Signalunterbrechungen gut behandeln.
Marcelo
6

open()ist ein Systemaufruf und spezifisch für Unix-basierte Systeme und gibt einen Dateideskriptor zurück. Sie können in einen Dateideskriptor schreiben, mit write()dem ein anderer Systemaufruf ausgeführt wird.
fopen()ist ein ANSI C-Funktionsaufruf, der einen Dateizeiger zurückgibt und auf andere Betriebssysteme portierbar ist. Wir können mit in einen Dateizeiger schreibenfprintf .

In Unix:
Sie können einen Dateizeiger aus dem Dateideskriptor abrufen, indem Sie:

fP = fdopen(fD, "a");

Sie können einen Dateideskriptor aus dem Dateizeiger abrufen, indem Sie:

fD = fileno (fP);
Arun Chettoor
quelle
4

open () wird am Ende jeder Funktion der fopen () -Familie aufgerufen . open () ist ein Systemaufruf und fopen () werden von Bibliotheken als Wrapper-Funktionen für den Benutzer bereitgestellt

theadnangondal
quelle
2

Ich habe für meine Anwendung von fopen () zu open () gewechselt, da fopen jedes Mal, wenn ich fopen fgetc ausführte, doppelte Lesevorgänge verursachte. Doppelte Lesevorgänge störten das, was ich erreichen wollte. open () scheint nur das zu tun, was Sie von ihm verlangen.

Ersatz Splatt
quelle
2

Hängt auch davon ab, welche Flags zum Öffnen erforderlich sind. In Bezug auf die Verwendung zum Schreiben und Lesen (und die Portabilität) sollte f * verwendet werden, wie oben dargelegt.

Wenn Sie jedoch grundsätzlich mehr als Standardflags (wie rw- und append-Flags) angeben möchten, müssen Sie eine plattformspezifische API (wie POSIX open) oder eine Bibliothek verwenden, die diese Details abstrahiert. Der C-Standard hat keine solchen Flags.

Beispielsweise möchten Sie eine Datei möglicherweise nur öffnen, wenn sie beendet wird. Wenn Sie das Erstellungsflag nicht angeben, muss die Datei vorhanden sein. Wenn Sie exklusiv zum Erstellen hinzufügen, wird die Datei nur erstellt, wenn sie nicht vorhanden ist. Es gibt viele mehr.

Auf Linux-Systemen gibt es beispielsweise eine LED-Schnittstelle, die über sysfs verfügbar gemacht wird. Es zeigt die Helligkeit der LED durch eine Datei. Schreiben oder Lesen einer Zahl als Zeichenfolge zwischen 0 und 255. Natürlich möchten Sie diese Datei nicht erstellen und nur dann in sie schreiben, wenn sie vorhanden ist. Das Coole jetzt: Verwenden Sie fdopen, um diese Datei mit den Standardaufrufen zu lesen / schreiben.

Ritualmeister
quelle
0

Öffnen einer Datei mit fopen,
bevor wir Informationen aus einer Datei auf einer Festplatte lesen (oder schreiben) können, müssen wir die Datei öffnen. Um die Datei zu öffnen, haben wir die Funktion fopen aufgerufen.

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.

Dies ist die Art und Weise des Verhaltens der Fopen- Funktion.
Es gibt einige Ursachen für den Pufferungsprozess. Es kann zu einer Zeitüberschreitung kommen. Beim Vergleichen von fopen (High Level I / O) mit offenem (Low Level I / O) Systemaufruf ist dies schneller und geeigneter als fopen .

Prashad
quelle
ist offen schneller als fopen?
Obayhan
Ja, offen ist der Systemaufruf, der schneller ist als fopen - vergleichsweise @obayhan
prashad