¿Hay alguna razón ordinaria de usar open () en lugar de fopen ()?
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).
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