Frage

Ich mache ein kleines Projekt in C nach einer recht lange Zeit weg von ihr. Dies geschieht, um eine Datei-Handling enthalten. Ich habe bemerkt, in verschiedener Dokumentation, dass es Funktionen, die FILE * Griffe und andere zurück, die (kleine ganze Zahl) Deskriptoren zurück. Beide Sätze von Funktionen die gleichen grundlegenden Dienste anbieten muss ich es so wirklich keine Rolle ich.

Aber ich bin neugierig auf die Sammlung Weisheit: ist es besser, fopen() und Freunde zu verwenden, oder open() und Freunde

Bearbeiten Da jemand vs ungepufferte und den Zugriff auf Geräte gepuffert erwähnt, sollte ich hinzufügen, dass ein Teil dieses kleine Projekt wird ein Userspace-Dateisystem-Treiber unter FUSE schreiben. So ist der Zugriff auf Dateiebene so einfach auf einem Gerät (zum Beispiel eines CD-ROM oder ein SCSI-Laufwerk), wie auf einer „Datei“ sein könnte (das heißt ein Bild).

War es hilfreich?

Lösung

Der Einwand, dass „fopen“ ist tragbar und „offen“ ist nicht gefälscht ist.

fopen Teil libc ist, offen ist ein POSIX-Systemaufruf.

Jeder ist so portabel wie der Ort, sie kommen.

i / o-Dateien fopen'ed wird (Sie davon ausgehen, muss es auch sein mag, und für praktische Zwecke wird) gepuffert durch libc, Filedeskriptoren open () "ed werden nicht von libc gepuffert (sie kann gut sein, und in der Regel werden im Dateisystem gepuffert -. aber nicht alles, was Sie öffnen () ist eine Datei auf einem Dateisystem

Was ist der Sinn von fopen'ing, beispielsweise ein Geräteknoten wie / dev / sg0, zu sagen oder / dev / tty0 ... Was werden Sie tun? Du wirst einen ioctl auf einem FILE * tun? Viel Glück damit.

Vielleicht möchten Sie mit einigen Fahnen wie O_DIRECT öffnen - macht keinen Sinn, mit fopen ()

.

Andere Tipps

Es ist besser, offen () zu verwenden, wenn Sie in der Unix-ähnlichen Systeme kleben und Sie vielleicht mögen:

  • Haben Sie mehr feinkörnige Kontrolle über Unix-Berechtigungs-Bits auf Dateierstellung.
  • Mit den Funktionen auf tieferer Ebene, wie beispielsweise Lesen / Schreiben / Mmap in Bezug auf die C Gegensatz gepufferten Strom I / O-Funktionen.
  • Verwenden Sie Dateideskriptor (fd) basierend IO Scheduling (Umfrage, wählen, etc.) Sie können natürlich einen fd aus einer Datei erhalten * mit fileno (), aber darauf, nicht FILE zu mischen * basierten Stromfunktionen getroffen werden müssen, mit fd basierte Funktionen.
  • Öffnen Sie ein beliebiges spezielles Gerät (keine reguläre Datei)

Es ist besser, verwenden fopen / fread / fwrite für maximale Portabilität, da diese Standard-C-Funktionen sind die Funktionen, die ich oben erwähnt habe, sind es nicht.

fopen Arbeiten auf einem höheren Niveau als offen .... fopen gibt Ihnen einen Zeiger Stream-Datei, die in die Stream Abstraktion ähnlich ist, die Sie in C ++ lesen

open kehren Sie eine Dateibeschreibung für die Datei geöffnet ... Es macht Sie keinen Strom Abstraktion liefern und Sie sind verantwortlich für die Bits und Bytes Umgang mit sich selbst ... Das auf einem niedrigeren Niveau ist im Vergleich zu fopen

Stdio Ströme werden gepuffert, während open () Filedeskriptoren nicht. Hängt davon ab, was Sie brauchen. Sie können auch eine vom anderen erstellen:

int fileno (FILE * stream) gibt den Dateideskriptor für einen FILE *, FILE * fdopen (int fildes, const char * Modus) erstellt eine Datei * von einem Dateideskriptor.

Seien Sie vorsichtig, wenn gepufferte Mischung und IO ungepufferten, da Sie verlieren, was in Ihrem Puffer ist, wenn Sie spülen Sie es nicht mit fflush ().

Ja. Wenn Sie einen Low-Level-Griff.

Unter UNIX-Betriebssystemen können Sie in der Regel tauschen Datei-Handles und Steckdosen.

Auch Low-Level-Griffe für eine bessere ABI-Kompatibilität als FILE-Pointer machen.

in der Regel, sollten Sie mit der Standardbibliothek (fopen) begünstigen. Es gibt jedoch Fälle, in denen Sie benötigen, um direkt öffnen können.

Ein Beispiel, das in den Sinn kommt, ist um einen Fehler in einer älteren Version von solaris zu arbeiten, die fopen gemacht fehlschlagen, nachdem 256 Dateien geöffnet waren. Das war, weil sie erroniously ein unsigned char für das fd Feld verwendet in ihrer Struktur FILE Implementierung anstelle eines int. Aber das war ein sehr spezieller Fall.

read () & write () verwenden ungepufferte E / A. ( fd : integer Dateideskriptor)

fread () & fwrite () Verwendung gepufferte I / O. ( Datei * Strukturzeiger)

Binärdaten an ein Rohr geschrieben mit write () kann nicht der Lage sein, mit binären Daten lesen fread () , wegen Byteausrichtungen, variable Größe, etc. Es ist ein Mist-shoot.

Die meisten Low-Level-Gerätetreiber-Code verwendet ungepufferte E / A-Anrufe.

Die meisten Anwendungsebene I / O-gepufferte verwendet.

Mit den Datei * und den dazugehörigen Funktionen ist auf einer Maschine-by-Maschine Basis OK aber Portabilität verloren auf anderen Architekturen in der Lesen und Schreiben von Binärdaten. fwrite () ist I / O gepuffert und zu unzuverlässigen Ergebnissen führen kann, wenn geschrieben für eine 64-Bit-Architektur und auf eine 32-Bit; oder (Windows / Linux). Die meisten Betriebssysteme haben Kompatibilität Makros in ihrem eigenen Code, um dies zu verhindern.

Für Low-Level-Binär-E / A-Portabilität lesen () und write () Garantie die gleiche binäre liest und schreibt, wenn sie auf unterschiedlichen Architekturen kompiliert werden. Die grundlegende Sache ist die eine oder die andere zu wählen und darüber übereinstimmen, während der gesamten binären Suite.

<stdio.h>  // mostly FILE*  some fd input/output parameters for compatibility
             // gives you a lot of helper functions -->
List of Functions
       Function      Description
       ───────────────────────────────────────────────────────────────────
       clearerr      check and reset stream status
       fclose        close a stream
       fdopen        stream open functions //( fd argument, returns FILE*)                      feof          check and reset stream status
       ferror        check and reset stream status
       fflush        flush a stream
       fgetc         get next character or word from input stream
       fgetpos       reposition a stream
       fgets         get a line from a stream
       fileno        get file descriptor   // (FILE* argument, returns fd) 
       fopen         stream open functions
       fprintf       formatted output conversion
       fpurge        flush a stream
       fputc         output a character or word to a stream
       fputs         output a line to a stream
       fread         binary stream input/output
       freopen       stream open functions
       fscanf        input format conversion
       fseek         reposition a stream
       fsetpos       reposition a stream
       ftell         reposition a stream
       fwrite        binary stream input/output
       getc          get next character or word from input stream
       getchar       get next character or word from input stream
       gets          get a line from a stream
       getw          get next character or word from input stream
       mktemp        make temporary filename (unique)
       perror        system error messages
       printf        formatted output conversion
       putc          output a character or word to a stream
       putchar       output a character or word to a stream
       puts          output a line to a stream
       putw          output a character or word to a stream
       remove        remove directory entry
       rewind        reposition a stream
       scanf         input format conversion
       setbuf        stream buffering operations
       setbuffer     stream buffering operations
       setlinebuf    stream buffering operations
       setvbuf       stream buffering operations
       sprintf       formatted output conversion
       sscanf        input format conversion
       strerror      system error messages
       sys_errlist   system error messages
       sys_nerr      system error messages
       tempnam       temporary file routines
       tmpfile       temporary file routines
       tmpnam        temporary file routines
       ungetc        un-get character from input stream
       vfprintf      formatted output conversion
       vfscanf       input format conversion
       vprintf       formatted output conversion
       vscanf        input format conversion
       vsprintf      formatted output conversion
       vsscanf       input format conversion

So für die grundlegende Nutzung würde ich persönlich die oben verwenden, ohne Idiome zu viel.

Misch

Im Gegensatz dazu

<unistd.h>   write()
             lseek()
             close()
             pipe()
<sys/types.h>
<sys/stat.h>
<fcntl.h>  open()
           creat()
           fcntl() 
all use file descriptors.

Diese bieten eine fein abgestimmte Kontrolle über das Lesen und Schreiben Bytes (Empfohlen für spezielle Geräte und fifos (Rohre)).

Also noch einmal, verwenden, was Sie brauchen, aber in Ihrem Idiom und Schnittstellen konsistent halten. Wenn die meisten Ihrer Code-Basis einen Modus verwendet, verwenden Sie das auch, es sei denn, es gibt ein echter Grund, nicht zu. Beide Sätze von I / O-Bibliotheksfunktionen sind extrem zuverlässig und verwendet Millionen Mal pro Tag.

note - Wenn Sie mit einer anderen Sprache C I / O sind Schnittstellen, (Perl, Python, Java, C #, lua ...) Besuche , was die Entwickler dieser Sprachen empfehlen, bevor Sie Ihren C-Code schreiben und sich etwas Mühe sparen.

fopen und seine Vettern gepuffert. Öffnen, Lesen und Schreiben nicht gepuffert werden. Ihre Anwendung kann oder auch nicht.

fprintf und scanf haben eine reichere API, die Sie lesen und schreiben formatierte Textdateien erlaubt. Lesen und Schreiben von grundlegenden Arrays von Bytes verwenden. Umwandlungen und Formatierungen müssen Hand gefertigt werden.

Der Unterschied zwischen Datei-Deskriptoren und (FILE *) ist wirklich belanglos.

Randy

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top