Pregunta

Estoy haciendo un pequeño proyecto en C después de un largo tiempo lejos de ella. Estos pasan a incluir algún manejo de archivos. Noté en diversos documentos que no son funciones que devuelven identificadores FILE * y otros que regresan descriptores (entero pequeño). Ambos conjuntos de funciones ofrecen los mismos servicios básicos que necesito por lo que realmente no importa lo uso.

Pero tengo curiosidad acerca de la conveniencia de recogida:? Es mejor usar amigos amigos y fopen() o open() y

Editar Desde Alguien mencionó tamponada vs dispositivos sin búfer y el acceso, debo añadir que una parte de este pequeño proyecto estará escribiendo un controlador de sistema de archivos en espacio de usuario bajo el fusible. Por lo que el acceso a nivel de archivo puede ser tan fácilmente en un dispositivo (por ejemplo, un CD-ROM o una unidad SCSI) como en un "archivo" (es decir, una imagen).

¿Fue útil?

Solución

La objeción de que "fopen" es portátil y "abierta" no es falso.

fopen es parte de libc, abierta es una llamada al sistema POSIX.

Cada uno es tan portátil como el lugar del que proceden.

I / O a fopen'ed Files es (usted debe asumir que sea, y para fines prácticos, es) amortiguada por libc, descriptores de archivo abierto) 'ed (no se amortigua por libc (que bien puede ser, y por lo general se almacenan temporalmente en el sistema de archivos -., pero no todo lo que abra () es un archivo en un sistema de archivos

¿Cuál es el punto de fopen'ing, por ejemplo, un nodo de dispositivo / dev / sg0, por ejemplo, o / dev / tty0 ... ¿Qué vas a hacer? Vas a una ioctl sobre un archivo *? Buena suerte con eso.

Tal vez usted quiere abrir con algunas banderas como O_DIRECT - no tiene sentido con fopen ()

.

Otros consejos

Es mejor utilizar open () si se están pegando a los sistemas de tipo Unix, y que le gustaría:

  • Tener un control más preciso sobre los bits de permisos UNIX en la creación del archivo.
  • Use las funciones de nivel inferior, tales como / escribir / leer mmap en comparación con el C tamponadas corriente I / funciones S.
  • Uso descriptor de archivo (fd) IO programación basada (sondeo, seleccionar, etc.) Por supuesto, puede obtener una fd desde un archivo * usando fileno (), pero se debe tener cuidado de no mezclar ARCHIVO * funciones de secuencia con base funciones basadas fd.
  • Abra cualquier dispositivo especial (no es un archivo normal)

Es mejor utilizar fopen / fread / fwrite para la máxima portabilidad, ya que estos son funciones de C estándar, las funciones que he mencionado anteriormente no son.

Producción fopen en un nivel superior al abierto .... fopen que devuelve un puntero al archivo de flujo que es similar a la abstracción corriente que lea en C ++

abiertos le devuelve un descriptor de archivo para el archivo abierto ... No le proporcionan una abstracción corriente y usted es responsable de manejar los bits y bytes a sí mismo ... Esto está en un nivel más bajo en comparación con fopen

corrientes Stdio se almacenan temporalmente, mientras abiertas () descriptores de fichero no lo son. Depende de lo que necesites. También puede crear una de la otra:

int fileno (FILE * stream) devuelve el descriptor de archivo para un archivo *, * ARCHIVO fdopen (int Fildes, const char * modo) crea un archivo * desde un descriptor de archivo.

Tenga cuidado al entremezclando amortiguada y no amortiguada IO, ya que si no se pierden lo que hay en el búfer cuando no lavarlo con fflush ().

Sí. Cuando necesite un mango de bajo nivel.

En los sistemas operativos UNIX, generalmente puede intercambiar identificadores de archivo y tomas de corriente.

Además, de bajo nivel se encarga de hacer para una mejor compatibilidad ABI que los punteros de archivos.

por lo general, se debe favorecer el uso de la biblioteca estándar (fopen). Sin embargo, hay ocasiones en las que tendrá que usar abren directamente.

Un ejemplo que viene a la mente es trabajar en torno a un error en una versión anterior de Solaris que hicieron fopen fallar después de 256 archivos abiertos. Esto se debió a que erroniously utilizan un unsigned char para el campo fd en su aplicación struct archivo en lugar de un int. Pero éste era un caso muy específico.

read () y write () utiliza sin búfer de E / S. ( fd : número entero descriptor de archivo)

fread () & fwrite () uso tamponada I / O. ( ARCHIVO * puntero de estructura)

Los datos binarios escritos en una tubería con write () no puede ser capaz de leer datos binarios con fread () , debido a las alineaciones de bytes, tamaños variables, etc. Es una porquería disparar.

La mayoría de código de controlador de dispositivo de bajo nivel usa llamadas de E / S sin almacenamiento intermedio.

La mayoría de nivel de aplicación de E / S utiliza tamponada.

El uso de los archivo * y sus funciones asociadas está bien sobre una base de máquina-a-máquina, pero se pierde la portabilidad en otras arquitecturas en la lectura y escritura de datos binarios. fwrite () es amortiguada de E / S y puede conducir a resultados poco fiables si escrito para una arquitectura de 64 bits y de 32 bits en un plazo; o (Windows / Linux). La mayoría de los sistemas operativos tienen las macros de compatibilidad dentro de su propio código para evitar esto.

Por lo binario de bajo nivel de portabilidad O / read () y write () Garantía el mismo binario lee y escribe cuando se compila en diferentes arquitecturas. Lo fundamental es escoger un modo u otro y ser coherente al respecto, toda la suite binario.

<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

Así que para el uso básico que usaría personalmente lo anterior sin mezclar modismos demasiado.

Por el contrario,

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

Estos proporcionan un control preciso sobre lectura y escritura de bytes (Recomendado para dispositivos y FIFOs (tuberías) especiales).

Así que de nuevo, utiliza lo que necesita, pero mantener constante en sus modismos y las interfaces. Si la mayor parte de su base de código utiliza un modo, utilizar eso también, a menos que haya una verdadera razón para no hacerlo. Ambos conjuntos de I / O funciones de la biblioteca son extremadamente fiables y se utilizan millones de veces al día.

Nota - Si el que interactúe C I / O con otro idioma, (Perl, Python, Java, C #, lua ...) Confirmar lo que los desarrolladores de esos idiomas recomendar antes de escribir el código C y ahorrar un poco de problemas.

fopen y sus primos se almacenan temporalmente. abrir, leer, y escribir no se han almacenado. Su aplicación puede o no puede cuidar.

fprintf y scanf tienen una API más rica que le permite leer y escribir archivos de texto con formato. leer y escribir utilizar matrices fundamentales de bytes. Las conversiones y el formato deben ser mano hecha a mano.

La diferencia entre los descriptores de archivos y (FILE *) es realmente insignificante.

Randy

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top