E/S de archivos en C

La versión actual de la página aún no ha sido revisada por colaboradores experimentados y puede diferir significativamente de la versión revisada el 13 de noviembre de 2018; las comprobaciones requieren 7 ediciones .

El lenguaje de programación C admite muchas funciones de biblioteca estándar para la entrada y salida de archivos . Estas funciones forman la base del archivo de encabezado de la biblioteca estándar de C. <stdio.h>

La funcionalidad de E/S del lenguaje C se implementa en un nivel bajo según los estándares actuales. El lenguaje C abstrae todas las operaciones de archivo en operaciones en flujos de bytes , que pueden ser "flujos de entrada" o "flujos de salida". A diferencia de algunos de los primeros lenguajes de programación, el lenguaje C no admite directamente el acceso aleatorio a los archivos de datos; para leer la información escrita en el medio del archivo, el programador tiene que crear un flujo que mire en el medio del archivo y luego leer secuencialmente los bytes del flujo.

El modelo de E/S de archivos de transmisión se popularizó en gran parte por el sistema operativo Unix escrito en C. Gran parte de la funcionalidad de los sistemas operativos modernos ha heredado flujos de Unix, y muchos lenguajes de la familia de lenguajes de programación C han heredado la interfaz de E/S de archivos C con pequeñas diferencias (por ejemplo, PHP ). La biblioteca estándar de C++ refleja el concepto de transmisión en su sintaxis (ver iostream ).

Abriendo un archivo con la función fopen

El archivo se abre con la función fopen, que devuelve información sobre el flujo de E/S adjunto al archivo especificado u otro dispositivo que se lee (o escribe). En caso de falla, la función devuelve un puntero nulo .

Una freopenfunción de biblioteca C similar realiza una operación similar después del primer cierre de cualquier flujo abierto asociado con sus parámetros.

Se anuncian como

ARCHIVO * fopen ( const char * ruta , const char * modo ); ARCHIVO * freopen ( const char * ruta , const char * modo , ARCHIVO * fp );

La función es esencialmente un "envoltorio" para una llamada al sistemafopen de nivel superior del sistema operativo Unix . Del mismo modo, es un envoltorio alrededor de una llamada al sistema Unix , y la estructura del lenguaje C en sí misma a menudo se refiere al descriptor de archivo Unix correspondiente. En un entorno POSIX , se puede usar una función para inicializar una estructura con un descriptor de archivo. Sin embargo, los descriptores de archivos como un concepto puramente Unix no están representados en el estándar del lenguaje C. open fclosecloseFILEfdopenFILE

El parámetro mode(modo) para fopeny freopendebe ser una cadena y comenzar con una de las siguientes secuencias:

modo descripción comienza con..
r rb se abre para leer comienzo
w wb se abre para escribir (crea un archivo si no existe). Elimina el contenido y sobrescribe el archivo. comienzo
a abdominales se abre para agregar (crea un archivo si no existe) final
r+ rb+ r+b se abre para leer y escribir comienzo
w+ wb+ w+b se abre para leer y escribir. Elimina el contenido y sobrescribe el archivo. comienzo
un+ ab+ a+b se abre para leer y escribir (crea un archivo si no existe) final

El valor " b " está reservado para el modo binario C. El estándar del lenguaje C define dos tipos de archivos, de texto y binarios  , aunque el sistema operativo no requiere que los distinga (sin embargo, para algunos compiladores, como LCC , especificando 'b' cuando se trabaja con un archivo binario es fundamentalmente importante!). Un archivo de texto  es un archivo que contiene texto dividido en líneas por algún carácter o secuencia de fin de línea delimitador (en Unix  , un solo salto de línea \n; en Microsoft Windows , un salto de línea va seguido de un retorno de carro ) \r\n. Al leer bytes de un archivo de texto, los caracteres de final de línea generalmente se asocian (reemplazan) con líneas nuevas para simplificar el procesamiento. Al escribir un archivo de texto, un solo carácter de nueva línea se asocia (reemplaza) con una secuencia específica del sistema operativo de caracteres de fin de línea antes de escribir. Un archivo binario  es un archivo desde el cual se leen y emiten bytes en forma "sin procesar" sin ningún enlace (sustitución).

Cuando se abre un archivo en modo de actualización (' + ' como el segundo o tercer carácter del argumento del designador de modo), tanto la entrada como la salida se pueden realizar en el mismo subproceso. Sin embargo, una escritura no puede seguir a una lectura sin una llamada intermedia fflusho una función de posición de archivo ( fseek, fsetposo rewind), y una lectura no puede seguir a una escritura sin una llamada intermedia a la función de posición de archivo. [una]

Los modos Escribir y Agregar intentan crear un archivo con el nombre dado si no existe tal archivo. Como se indicó anteriormente, si esta operación falla, fopendevuelve NULL.

Cerrar una secuencia con fclose

La función fclosetoma un argumento: un puntero a la estructura de flujo FILEpara cerrar.

int fclose ( ARCHIVO * fp );

La función devuelve cero en caso de éxito y EOF en caso de error. Cuando el programa termina normalmente, la función se llama automáticamente para cada archivo abierto.

Lectura de un flujo

con fgetc

La función fgetcse utiliza para leer un carácter de la secuencia.

int fgetc ( ARCHIVO * fp );

Si tiene éxito fgetc, devuelve el siguiente byte o carácter de la secuencia (dependiendo de si el archivo es "binario" o "texto", como se explicó anteriormente). De lo contrario fgetcvuelve EOF. (Un tipo particular de error se puede identificar mediante una llamada ferroro feofcon un puntero de archivo).

Una macro getc estándar también se define en <stdio.h>, funcionando correctamente como fgetc, excepto por una cosa: al ser una macro, puede procesar sus argumentos más de una vez.

La función estándar getchartambién se define en <stdio.h>, no toma argumentos y es equivalente a . getc(stdin)

"Trampa" EOF

Un error común es usar o asignar el resultado a una variable de tipo fgetcantes de compararlo con . El siguiente fragmento de código demuestra este error y la versión correcta se muestra junto a él: getcgetcharchar EOF

Error Correctamente
carcter c ; while (( c = getchar ()) != EOF ) { poner ( c ); } intc ; _ while (( c = getchar ()) != EOF ) { poner ( c ); }

Considere un sistema en el que un tipo charde 8 bits de largo (específicamente la arquitectura x86 ) representa 256 valores distintos. getcharpuede devolver cualquiera de los 256 caracteres posibles, y también puede volver EOFpara indicar el final del archivo, cuyo valor no puede coincidir con ninguno de los valores de char.

Cuando el resultado getcharse asigna a una variable de tipo char, que solo puede representar 256 valores diferentes, se produce una pérdida forzada de información: cuando se comprimen 257 valores en 256 “lugares” , se produce una colisión . El valor EOFcuando se convierte a charse vuelve indistinguible de cualquiera de los otros 256 caracteres. Si este carácter se encuentra en un archivo, el código anterior podría tomarlo como un final de archivo, o peor aún, si el tipo char no está firmado, dado que EOF - es un valor negativo, nunca puede ser igual a ningún sin firmar char. el ejemplo anterior no terminará en la marca de fin de archivo, sino que se ejecutará para siempre, reimprimiendo el carácter resultante de la conversión EOFa char.

En sistemas donde inty charson del mismo tamaño[ ¿Qué? ] , incluso la versión "correcta" no funcionará correctamente debido a la similitud EOFy otro carácter. La forma correcta de manejar esta situación es verificar feofy ferrordespués de que getcharregrese EOF. Si feofdetecta que aún no se ha llegado al final del archivo, pero ferror"informa" que no hay errores, entonces el EOFdevuelto getcharpuede considerarse el carácter actual. Estas comprobaciones adicionales rara vez se realizan, ya que la mayoría de los programadores asumen que su código nunca se ejecutará en charsistemas tan "grandes". Otra forma es usar una verificación en tiempo de compilación que UINT_MAX > UCHAR_MAXal menos prevenga la compilación en dichos sistemas.

con fgets

La función fgetsse utiliza para leer una cadena de una secuencia. La lectura continúa hasta el final de la línea ( hex :0D0A, equivalente en listados a \n ) o se alcanza la longitud de la línea que se está leyendo. Supongamos que tenemos un archivo some_file.txt con texto

palíndromos Y en el Yenisei - azul. Y la llama es pequeña. Y el zorro, es inteligente: la rata le puso queso. (I. Babitsky) #incluir <stdio.h> #incluir <cadena.h> int main ( int argc , char * argv []) /* argc almacena el número de parámetros y argv[] apunta a esos parámetros. Por ejemplo, si ejecutamos el ejecutable "fgets_example param1 param2", entonces argc será igual a 3 y argv[] = { "fgets_example" , "param1" , "param2" } */ { ARCHIVO * archivo ; char * fname = "algun_archivo.txt" ; char resultado_cadena [ 20 ]; //Cadena de 20 caracteres archivo = fopen ( fname , "r" ); si ( archivo == NULL ) { printf ( "no se puede abrir el archivo '%s'" , fname ); devolver 0 ; } int i = 0 ; char * cola_real ; while ( fgets ( resultado_cadena , tamaño de ( resultado_cadena ), archivo )) { cola_real = "" ; printf ( "Cadena %d:Longitud de la cadena - %d:" , i ++ , strlen ( cadena_resultado )); if ( result_string [ strlen ( result_string ) -1 ] == '\n' ) // comprueba si el último elemento de la cadena es el carácter final { real_tail = " \\ n" ; cadena_resultado [ strlen ( cadena_resultado ) -1 ] = '\0' ; }; // esta parte del código se agregó solo para mostrar el carácter de fin de línea en la consola sin una nueva línea printf ( "%s%s \n " , result_string , real_tail ); } fclose ( archivo ); devolver 0 ; }

como resultado de la ejecución obtendremos

Línea 0:Longitud de línea - 11:palíndromos\n Línea 1: Longitud de la línea - 19: Y en el Yenisei - si Línea 2:Longitud de línea - 6:neva.\n Línea 3: La longitud de la línea es 17: Y la llama es pequeña.\n Línea 4: Longitud de la línea - 19: Un zorro, es inteligente Línea 5: Longitud de línea - 19: - queso de rata Línea 6: Longitud de la línea - 19: desgastado. (I. Babitsky Línea 7: Longitud de línea - 2:th)

La función strlen determina la longitud de una cadena por el número de caracteres hasta '\0', por ejemplo:

printf ( "%d" , strlen ( "123 \0 123" )); // salidas 4

escribir

En el lenguaje de programación C, las funciones fready fwriterespectivamente implementan operaciones de entrada y salida de archivos . y declarado en . freadfwrite <stdio.h>

Escribir en un archivo con fwrite

fwrite se define como

int fwrite ( const char * array , size_t size , size_t count , FILE * stream );

La función fwriteescribe un bloque de datos en la secuencia. Esto escribirá una matriz de elementos arrayen la posición actual en la secuencia. sizeSe escribirá un byte para cada elemento . El indicador de posición de flujo cambiará al número de bytes escritos correctamente. El valor devuelto será igual counta si la escritura se completó con éxito. En caso de error, el valor devuelto será menor que count.

El siguiente programa abre un archivo .txt de ejemplo , escribe una cadena de caracteres y luego lo cierra.

#incluir <stdio.h> #incluir <cadena.h> #incluir <stdlib.h> int principal ( vacío ) { ARCHIVO * fp ; tamaño_t cuenta ; char const * str = "hola \n " ; fp = fopen ( "ejemplo.txt" , "wb" ); si ( fp == NULL ) { perror ( "error al abrir ejemplo.txt" ); devuelve EXIT_FAILURE ; } cuenta = fwrite ( str , sizeof ( char ), strlen ( str ), fp ); printf ( "%lu bytes escritos. fclose(fp) %s. \n " , ( unsigned long ) count , fclose ( fp ) == 0 ? "éxito" : "error" ); fcerrar ( fp ); devolver 0 ; }

Escribiendo en un flujo con fputc

La función fputcse utiliza para escribir un carácter en la secuencia.

int fputc ( int c , ARCHIVO * fp );

La copción silenciosa se convierte unsigned charantes de la salida. Si tiene éxito, fputcdevuelve el carácter escrito. Si hay un error, entonces fputcdevuelve EOF.

Una macro estándar putctambién se define en <stdio.h>, que funciona de la misma manera en general fputc, excepto que, como macro, puede procesar sus argumentos más de una vez.

La función estándar putchar, también definida en <stdio.h>, toma solo el primer argumento y es equivalente a , donde se menciona el argumento. putc(c, stdout)c

Ejemplo de uso

El siguiente programa en C abre un archivo binario llamado myfile , lee cinco bytes y luego cierra el archivo.

#incluir <stdio.h> #incluir <stdlib.h> int principal ( vacío ) { búfer de caracteres [ 5 ] = { 0 } ; /* inicializar con ceros */ int i , rc ; ARCHIVO * fp = fopen ( "miarchivo" , "rb" ); si ( fp == NULL ) { perror ( "Error al abrir \" miarchivo \" " ); devuelve EXIT_FAILURE ; } for ( i = 0 ; ( rc = getc ( fp )) != EOF && i < 5 ; buffer [ i ++ ] = rc ); fcerrar ( fp ); si ( yo == 5 ) { puts ( "Bytes leídos..." ); printf ( "%x %x %x %x %x \n " , búfer [ 0 ], búfer [ 1 ], búfer [ 2 ], búfer [ 3 ], búfer [ 4 ]); } más fputs ( "Error al leer el archivo. \n " , stderr ); devuelve SALIR_ÉXITO ; }

Véase también

Fuentes adicionales