C fopen vs abierto

219

¿Hay alguna razón (aparte de las sintácticas) que quiera usar

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

o

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

en vez de

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

cuando se usa C en un entorno Linux?

LJM
fuente
¿Quiso decir fdopeny openo o fopeny open?
user7116
¿No quieres decir fopen, no fdopen?
Omnifarious
99
fopenes parte de la biblioteca estándar de C, openno lo es. Úselo fopenal escribir código portátil.
Aziz el
Sí, me refería a fopen. Lo acabo de actualizar, pero creo que se aplica el mismo principio.
LJM
66
@Aziz, sin embargo, openes una función POSIX.
dreamlax el

Respuestas:

242

Primero, no hay una razón particularmente buena para usar fdopensi fopenes una opción y openes la otra opción posible. En openprimer lugar , no debería haber usado para abrir el archivo si desea un FILE *. Por lo tanto, incluirlo fdopenen esa lista es incorrecto y confuso porque no se parece mucho a los demás. Ahora procederé a ignorarlo porque la distinción importante aquí es entre un estándar C FILE *y un descriptor de archivo específico del sistema operativo.

Hay cuatro razones principales para usar en fopenlugar de open.

  1. fopenle proporciona IO de almacenamiento en búfer que puede resultar mucho más rápido de lo que está haciendo open.
  2. fopen realiza la traducción de final de línea si el archivo no se abre en modo binario, lo que puede ser muy útil si su programa alguna vez se transfiere a un entorno que no sea Unix (aunque el mundo parece converger solo en LF (excepto la red basada en texto IETF) protocolos como SMTP y HTTP y tal)).
  3. A FILE *le brinda la capacidad de usar fscanfy otras funciones estándar.
  4. Es posible que algún día sea necesario portar su código a otra plataforma que solo sea compatible con ANSI C y no sea compatible con la openfunción.

En mi opinión, la traducción de final de línea se interpone en su camino más de lo que lo ayuda, y el análisis fscanfes tan débil que inevitablemente termina desechando a favor de algo más útil.

Y la mayoría de las plataformas que admiten C tienen una openfunción.

Eso deja la pregunta de amortiguación. En lugares donde está leyendo o escribiendo un archivo principalmente de forma secuencial, el soporte de almacenamiento en búfer es realmente útil y una gran mejora de la velocidad. Pero puede conducir a algunos problemas interesantes en los que los datos no terminan en el archivo cuando espera que estén allí. Tienes que recordar fcloseo fflushen los momentos apropiados.

Si está haciendo búsquedas (alias fsetposo fseekla segunda de las cuales es un poco más difícil de usar de una manera que cumple con los estándares), la utilidad del almacenamiento en búfer disminuye rápidamente.

Por supuesto, mi sesgo es que tiendo a trabajar mucho con sockets, y existe el hecho de que realmente quieres estar haciendo IO sin bloqueo (que FILE *no es compatible de ninguna manera razonable) sin ningún buffering y a menudo Tengo requisitos de análisis complejos que realmente colorean mis percepciones.

De todo género
fuente
44
No voy a cuestionar tus experiencias, pero me encantaría escucharte explicar un poco sobre esto. ¿Para qué tipo de aplicaciones cree que el almacenamiento en búfer incorporado se interpone? ¿Cuál es exactamente el problema?
Emil H el
1
No vi el último párrafo. Punto válido, en mi humilde opinión. Sin embargo, hasta donde puedo decir, la pregunta era sobre el archivo IO.
Emil H
77
Para aclarar cuando el buffering se interpone en el camino. Es cuando usas buscar. La siguiente lectura con cualquier comando ( fgets, fgetc, fscanf, fread), siempre leer el tamaño de la memoria intermedia (4K, 8K o cualquier cosa que se). Al usar la E / S directa puede evitar eso. En ese caso, es incluso mejor usar en preadlugar de un par de búsqueda / lectura (1 syscall en lugar de 2).
Patrick Schlüter
2
El manejo interrumpido read()y las write()llamadas es una quinta razón conveniente para usar la familia de funciones libc.
nccc
3
@ m-ric: Bueno, esa es una pregunta algo no relacionada, pero sí. Todas las plataformas compatibles ioctltambién admiten la filenollamada que toma un FILE *y devuelve un número que se puede usar en una ioctlllamada. Pero ten cuidado. FILE *las llamadas relacionadas pueden interactuar sorprendentemente con el uso ioctlpara cambiar algo sobre el descriptor de archivo subyacente.
Omnifarioso
53

open()es una llamada de bajo nivel del sistema operativo. fdopen()convierte un descriptor de archivo de nivel os en la abstracción de ARCHIVO de nivel superior del lenguaje C. fopen()llama open()en segundo plano y te da un puntero de ARCHIVO directamente.

Existen varias ventajas al usar objetos FILE en lugar de descriptores de archivos sin formato, que incluyen una mayor facilidad de uso, pero también otras ventajas técnicas, como el almacenamiento en búfer incorporado. Especialmente el almacenamiento en búfer generalmente da como resultado una ventaja de rendimiento considerable.

Emil H
fuente
3
¿Hay alguna desventaja en usar las versiones 'f ...' almacenadas de open?
LJM
55
@L. Moser, sí, cuando ya está almacenando los datos en el búfer y, por lo tanto, el búfer adicional agrega copia innecesaria y sobrecarga de memoria.
Michael Aaron Safyan el
66
En realidad hay otras desventajas. fopen()no proporciona el mismo nivel de control al abrir archivos, por ejemplo, crear permisos, modos de compartir y más. Por lo general, las open()variantes proporcionan mucho más control, cerca de lo que realmente proporciona el sistema operativo
Matt Joiner el
2
También hay casos extremos en los que mmapel archivo y los cambios se realizan con E / S normales (por increíble que parezca que en realidad lo hacemos en nuestro proyecto y por razones realmente buenas), el almacenamiento en búfer estaría en el camino.
Patrick Schlüter
También es posible que desee utilizar otras funciones del sistema, como usar open () para precargar archivos en la memoria caché de la página a través de readahead (). Supongo que la regla general es "usar fopen a menos que sea absolutamente necesario abrir ()", open () en realidad te permite hacer cosas elegantes (configurar / no configurar O_ATIME y similares).
Tomás Pruzina
34

fopen vs abierto en C

1) fopenes una función de biblioteca mientras que openes una llamada al sistema .

2) fopenproporciona IO con buffer que es más rápido en comparación con el openque no tiene buffer .

3) fopenes portátil mientras que openno es portátil ( abierto es específico del entorno ).

4) fopendevuelve un puntero a una estructura FILE (FILE *) ; opendevuelve un entero que identifica el archivo.

5) A FILE *le brinda la capacidad de usar fscanf y otras funciones estándar.

Yogeesh HT
fuente
99
openes un estándar POSIX, por lo que es bastante portátil
osvein 05 de
12

A menos que forme parte del 0.1% de las aplicaciones en las que el uso openes un beneficio de rendimiento real, realmente no hay una buena razón para no usarlo fopen. En lo que a él fdopenrespecta, si no estás jugando con descriptores de archivos, no necesitas esa llamada.

Palo con el fopeny su familia de métodos ( fwrite, fread, fprintf, y otros) y se le muy satisfecho. Igual de importante, otros programadores estarán satisfechos con su código.

usuario7116
fuente
11

Si usted tiene una FILE *, puede utilizar funciones como fscanf, fprintfy fgetsetc Si usted tiene sólo el descriptor de archivo, usted ha limitado (pero probablemente más rápido) de entrada y salida rutinas read, writeetc.

dreamlax
fuente
7

El uso de abrir, leer y escribir significa que debe preocuparse por las interacciones de señal.

Si la llamada fue interrumpida por un controlador de señal, las funciones devolverán -1 y establecerán errno en EINTR.

Entonces, la forma correcta de cerrar un archivo sería

while (retval = close(fd), retval == -1 && ernno == EINTR) ;
digy
fuente
44
Para close, esto depende del sistema operativo. Es incorrecto hacer el bucle en Linux, AIX y algunos otros sistemas operativos.
strcat
Además, el uso de lectura y escritura sufrirá el mismo problema, es decir, pueden ser interrumpidos por una señal antes de procesar la entrada / salida por completo y el programador debe manejar tales situaciones, mientras que fread y fwrite manejan las interrupciones de la señal de manera agradable.
Marcelo
6

open()es una llamada al sistema y específica de los sistemas basados ​​en Unix y devuelve un descriptor de archivo. Puede escribir en un descriptor de archivo utilizando write()otra llamada del sistema.
fopen()es una llamada de función ANSI C que devuelve un puntero de archivo y es portátil a otros sistemas operativos. Podemos escribir en un puntero de archivo usando fprintf.

En Unix:
puede obtener un puntero de archivo desde el descriptor de archivo usando:

fP = fdopen(fD, "a");

Puede obtener un descriptor de archivo desde el puntero del archivo usando:

fD = fileno (fP);
Arun Chettoor
fuente
4

Se llamará a open () al final de cada una de las funciones de la familia fopen () . open () es una llamada al sistema y las bibliotecas proporcionan fopen () como funciones envolventes para un usuario fácil de usar

theadnangondal
fuente
2

Cambié a open () desde fopen () para mi aplicación, porque fopen estaba causando lecturas dobles cada vez que ejecutaba fopen fgetc. Las lecturas dobles fueron perjudiciales para lo que estaba tratando de lograr. open () parece hacer lo que le pides.

Ersatz Splatt
fuente
2

Depende también de qué banderas se requieren para abrir. Con respecto al uso para escribir y leer (y portabilidad) se debe usar f *, como se argumentó anteriormente.

Pero si básicamente desea especificar más que banderas estándar (como rw y agregar banderas), tendrá que usar una API específica de la plataforma (como POSIX abierto) o una biblioteca que abstraiga estos detalles. El estándar C no tiene tales banderas.

Por ejemplo, es posible que desee abrir un archivo, solo si sale. Si no especifica la marca de creación, el archivo debe existir. Si agrega exclusivo para crear, solo creará el archivo si no existe. Hay muchos más.

Por ejemplo, en sistemas Linux hay una interfaz LED expuesta a través de sysfs. Expone el brillo del led a través de un archivo. Escribir o leer un número como una cadena que va de 0 a 255. Por supuesto, no desea crear ese archivo y solo escribir en él si existe. Lo bueno ahora: usa fdopen para leer / escribir este archivo usando las llamadas estándar.

Maestro de rituales
fuente
0

Al abrir un archivo usando fopen
antes de que podamos leer (o escribir) información de (a) un archivo en un disco, debemos abrir el archivo. para abrir el archivo hemos llamado a la función 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.

Esta es la forma de comportamiento de la función fopen .
Hay algunas causas durante el proceso de almacenamiento en búfer, puede agotar el tiempo de espera. así que, al comparar fopen ( E / S de alto nivel) con la llamada al sistema abierto (E / S de bajo nivel), es más rápido y apropiado que fopen .

prashad
fuente
está abierto más rápido que fopen?
obayhan
sí, abierta es la llamada al sistema, que es más rápido que fopen - comparativamente @obayhan
prashad