Antworten:
Ein Dateideskriptor ist ein ganzzahliges "Handle" auf niedriger Ebene, mit dem eine geöffnete Datei (oder ein Socket oder was auch immer) auf Kernelebene unter Linux und anderen Unix-ähnlichen Systemen identifiziert wird.
Sie passieren „nackt“ Dateideskriptoren tatsächliche Unix Anrufe, wie read()
, write()
und so weiter.
Ein FILE
Zeiger ist ein C-Standardkonstrukt auf Bibliotheksebene, das zur Darstellung einer Datei verwendet wird. Das FILE
umschließt den Dateideskriptor und fügt Pufferung und andere Funktionen hinzu, um die E / A zu vereinfachen.
Sie übergeben FILE
Zeiger auf Standard-C-Funktionen wie fread()
und fwrite()
.
fd
das erste Argument ist read()
. Warum nennst du es nackt?
FILE *
Typ der Standardbibliothek ist der Integer-Dateideskriptor "weniger umbrochen", dh "nackt".
Einer ist gepuffert ( FILE *
) und der andere nicht. In der Praxis möchten Sie FILE *
fast immer verwenden, wenn Sie aus einer "echten" Datei (dh auf dem Laufwerk) lesen, es sei denn, Sie wissen, was Sie tun, oder Ihre Datei ist tatsächlich ein Socket oder so.
Sie können den Dateideskriptor mit FILE *
using abrufen fileno()
und einen gepufferten FILE *
Dateideskriptor mit using öffnenfdopen()
Ein Dateideskriptor ist nur eine Ganzzahl, die Sie aus dem POSIX- open()
Aufruf erhalten. Mit dem Standard C erhalten fopen()
Sie eine FILE
Struktur zurück. Die FILE
Struktur enthält diesen Dateideskriptor unter anderem wie Dateiende- und Fehleranzeige, Stream-Position usw.
fopen()
Wenn Sie also verwenden, erhalten Sie im Vergleich zu eine gewisse Abstraktion open()
. Im Allgemeinen sollten Sie verwenden, fopen()
da dies portabler ist und Sie alle anderen Standard-C-Funktionen verwenden können, die die FILE
Struktur, dh fprintf()
und die Familie verwenden.
Es gibt auch keine Leistungsprobleme bei der Verwendung.
Dateideskriptor vs Dateizeiger
Dateideskriptor:
Der Dateideskriptor ist ein ganzzahliger Wert, der vom open()
Systemaufruf zurückgegeben wird.
int fd = open (filePath, mode);
Dateizeiger:
Der Dateizeiger ist ein Zeiger auf eine C-Struktur, die von der fopen()
Bibliotheksfunktion zurückgegeben wird. Er dient zum Identifizieren einer Datei, zum Umschließen des Dateideskriptors, zum Puffern und für alle anderen Funktionen, die für die E / A-Operation erforderlich sind. Der Dateizeiger ist vom Typ FILE , dessen Definition finden Sie in "/usr/include/stdio.h" . Diese Definition kann von Compiler zu Compiler unterschiedlich sein.
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;
Möchten Sie Punkte hinzufügen, die nützlich sein könnten.
ÜBER FILE *
Ich benutze es oft für Debug-Protokolle. Beispiel,
FILE *fp;
fp = fopen("debug.txt","a");
fprintf(fp,"I have reached till this point");
fclose(fp);
ÜBER FILE DESCRIPTOR
Es wird im Allgemeinen für IPC verwendet.
Ermöglicht die einfache Steuerung von Dateien auf * nix-Systemen (Geräte, Dateien, Sockets usw.) und ist daher leistungsfähiger als die FILE *
.
fdopen()
nicht Dinge wie IPC und Geräte mit tun FILE*
?
FILE*
, aber Sie können einen FILE*
aus einem Dateideskriptor ( fdopen()
) erstellen und später schließen FILE
, um den Deskriptor ebenfalls zu schließen. Daher können Sie IPC ausführen, müssen sich jedoch ein wenig mit Dateideskriptoren befassen, um einen direkten IPC zu ermöglichen.
FILE *
ist nützlich , wenn Sie mit Textdateien und Benutzereingabe / Ausgabe arbeiten, weil es Ihnen wie API - Funktionen verwenden kann sprintf()
, sscanf()
, fgets()
, feof()
usw.
Die Dateideskriptor-API ist auf niedriger Ebene und ermöglicht daher die Arbeit mit Sockets, Pipes, Dateien mit Speicherzuordnung (und natürlich mit regulären Dateien).
Nur eine Notiz zum Abschluss der Diskussion (falls interessiert) ....
fopen
kann unsicher sein, und Sie sollten wahrscheinlich fopen_s
oder open
mit exklusiven gesetzten Bits verwenden. C1X bietet x
Modi, so können Sie fopen
mit Modi "rx"
, "wx"
usw.
Wenn Sie verwenden open
, könnten Sie open(..., O_EXCL | O_RDONLY,... )
oder in Betracht ziehen open(..., O_CREAT | O_EXCL | O_WRONLY,... )
.
Siehe zum Beispiel: Machen Sie keine Annahmen über fopen () und die Dateierstellung .
fopen_s
es anscheinend nicht verfügbar ist POSIX
, gehe ich davon aus, dass die tragbarste Lösung für open(2)
und dann ist fdopen(2)
. (Fenster beiseite lassen). Was wäre schneller fopen_s()
oder open(2)
gefolgt von fdopen(2)
?
Systemaufrufe verwenden zum Beispiel meistens den Dateideskriptor read
und write
. Die Bibliotheksfunktion verwendet die Dateizeiger ( printf
, scanf
). Bibliotheksfunktionen verwenden jedoch nur interne Systemaufrufe.
Ich habe hier eine gute Ressource gefunden , die einen umfassenden Überblick über die Unterschiede zwischen den beiden gibt:
Wenn Sie eine Datei eingeben oder ausgeben möchten, haben Sie die Wahl zwischen zwei grundlegenden Mechanismen zur Darstellung der Verbindung zwischen Ihrem Programm und der Datei: Dateideskriptoren und Streams. Dateideskriptoren werden als Objekte vom Typ int dargestellt, während Streams als FILE * -Objekte dargestellt werden.
Dateideskriptoren bieten eine primitive Schnittstelle für Eingabe- und Ausgabeoperationen auf niedriger Ebene. Sowohl Dateideskriptoren als auch Streams können eine Verbindung zu einem Gerät (z. B. einem Terminal) oder einer Pipe oder einem Socket für die Kommunikation mit einem anderen Prozess sowie eine normale Datei darstellen. Wenn Sie jedoch Steuerungsvorgänge ausführen möchten, die für einen bestimmten Gerätetyp spezifisch sind, müssen Sie einen Dateideskriptor verwenden. Es gibt keine Möglichkeit, Streams auf diese Weise zu verwenden. Sie müssen auch Dateideskriptoren verwenden, wenn Ihr Programm Eingaben oder Ausgaben in speziellen Modi ausführen muss, z. B. nicht blockierende (oder abgefragte) Eingaben (siehe Dateistatus-Flags).
Streams bieten eine übergeordnete Schnittstelle, die über den primitiven Dateideskriptorfunktionen liegt. Die Stream-Oberfläche behandelt alle Arten von Dateien ziemlich ähnlich - die einzige Ausnahme sind die drei Pufferstile, die Sie auswählen können (siehe Stream-Pufferung).
Der Hauptvorteil der Verwendung der Stream-Schnittstelle besteht darin, dass der Satz von Funktionen zum Ausführen tatsächlicher Eingabe- und Ausgabeoperationen (im Gegensatz zu Steueroperationen) für Streams viel umfangreicher und leistungsfähiger ist als die entsprechenden Funktionen für Dateideskriptoren. Die Dateideskriptor-Schnittstelle bietet nur einfache Funktionen zum Übertragen von Zeichenblöcken, aber die Stream-Schnittstelle bietet auch leistungsstarke formatierte Eingabe- und Ausgabefunktionen (printf und scanf) sowie Funktionen für die zeichen- und zeilenorientierte Eingabe und Ausgabe.
Da Streams in Form von Dateideskriptoren implementiert sind, können Sie den Dateideskriptor aus einem Stream extrahieren und Operationen auf niedriger Ebene direkt am Dateideskriptor ausführen. Sie können eine Verbindung auch zunächst als Dateideskriptor öffnen und dann einen Stream erstellen, der diesem Dateideskriptor zugeordnet ist.
Im Allgemeinen sollten Sie Streams anstelle von Dateideskriptoren verwenden, es sei denn, Sie möchten eine bestimmte Operation ausführen, die nur für einen Dateideskriptor ausgeführt werden kann. Wenn Sie ein Anfänger sind und sich nicht sicher sind, welche Funktionen Sie verwenden sollen, empfehlen wir Ihnen, sich auf die formatierten Eingabefunktionen (siehe Formatierte Eingabe) und die formatierten Ausgabefunktionen (siehe Formatierte Ausgabe) zu konzentrieren.
Wenn Sie Bedenken hinsichtlich der Portabilität Ihrer Programme auf andere Systeme als GNU haben, sollten Sie sich auch darüber im Klaren sein, dass Dateideskriptoren nicht so portabel sind wie Streams. Sie können davon ausgehen, dass jedes System, auf dem ISO C ausgeführt wird, Streams unterstützt, aber Nicht-GNU-Systeme unterstützen möglicherweise überhaupt keine Dateideskriptoren oder implementieren nur eine Teilmenge der GNU-Funktionen, die mit Dateideskriptoren arbeiten. Die meisten Dateideskriptorfunktionen in der GNU C-Bibliothek sind jedoch im POSIX.1-Standard enthalten.