Está en la página 1de 179

Informática I

Claudio Paz

claudiojpaz@gmail.com

Noviembre 2023

1
Unidad 11
Manejo de archivos en C

2
Concepto de Flujo de datos (streams)

3
Concepto de Flujo de datos (streams)
La mayoría de los programas necesitan entradas (in) o salidas
(out), o ambas.

3
Concepto de Flujo de datos (streams)
La mayoría de los programas necesitan entradas (in) o salidas
(out), o ambas.

El lenguaje C NO dispone de sentencias de entrada/salida.

3
Concepto de Flujo de datos (streams)
La mayoría de los programas necesitan entradas (in) o salidas
(out), o ambas.

El lenguaje C NO dispone de sentencias de entrada/salida.

Hay que recurrir a una biblioteca que tenga funciones para


manejar las entrada/salidas.

3
Concepto de Flujo de datos (streams)
La mayoría de los programas necesitan entradas (in) o salidas
(out), o ambas.

El lenguaje C NO dispone de sentencias de entrada/salida.

Hay que recurrir a una biblioteca que tenga funciones para


manejar las entrada/salidas.

Las funciones de la biblioteca estándar están declaradas en el


archivo de cabecera stdio.h

3
Concepto de Flujo de datos (streams)

4
Concepto de Flujo de datos (streams)
Todas las entradas y salidas son simplemente secuencias de
bytes que van de un lado a otro, llamadas streams

4
Concepto de Flujo de datos (streams)
Todas las entradas y salidas son simplemente secuencias de
bytes que van de un lado a otro, llamadas streams

Las entradas son bytes que van desde dispositivos (teclado,


disco, red) hacia la memoria

4
Concepto de Flujo de datos (streams)
Todas las entradas y salidas son simplemente secuencias de
bytes que van de un lado a otro, llamadas streams

Las entradas son bytes que van desde dispositivos (teclado,


disco, red) hacia la memoria

Las salidas son bytes que van desde la memoria a un


dispositivo (pantalla, impresora, disco, red)

4
Concepto de Flujo de datos (streams)

5
Concepto de Flujo de datos (streams)
Cuando un programa comienza, ya tiene tres streams
estándar predefinidos, listos para su uso...

5
Concepto de Flujo de datos (streams)
Cuando un programa comienza, ya tiene tres streams
estándar predefinidos, listos para su uso...

...están declarados en stdio.h

5
Concepto de Flujo de datos (streams)
Cuando un programa comienza, ya tiene tres streams
estándar predefinidos, listos para su uso...

...están declarados en stdio.h

stdin es la entrada y está conectada al teclado.

5
Concepto de Flujo de datos (streams)
Cuando un programa comienza, ya tiene tres streams
estándar predefinidos, listos para su uso...

...están declarados en stdio.h

stdin es la entrada y está conectada al teclado.

stdout es la salida y está conectada a la pantalla.

5
Concepto de Flujo de datos (streams)
Cuando un programa comienza, ya tiene tres streams
estándar predefinidos, listos para su uso...

...están declarados en stdio.h

stdin es la entrada y está conectada al teclado.

stdout es la salida y está conectada a la pantalla.

stderr es la salida de error y está conectada a la pantalla.

5
Concepto de Flujo de datos (streams)

6
Concepto de Flujo de datos (streams)
El SO puede permitir redireccionarlos a otros dispositivos.

6
Concepto de Flujo de datos (streams)
El SO puede permitir redireccionarlos a otros dispositivos.

Tanto stdin, stdout y stderr son de tipo FILE *

6
Concepto de Flujo de datos (streams)
El SO puede permitir redireccionarlos a otros dispositivos.

Tanto stdin, stdout y stderr son de tipo FILE *

FILE * es un tipo de datos usado para representar streams

6
Concepto de Flujo de datos (streams)
El SO puede permitir redireccionarlos a otros dispositivos.

Tanto stdin, stdout y stderr son de tipo FILE *

FILE * es un tipo de datos usado para representar streams

Es una estructura con información necesaria para el manejo


en bajo nivel de los archivos.

6
El tipo FILE *

7
El tipo FILE *
El tipo FILE es una estructura definida en stdio.h que
contiene información para procesar el archivo

7
El tipo FILE *
El tipo FILE es una estructura definida en stdio.h que
contiene información para procesar el archivo

Esta estructura contiene un descriptor de archivo, que no es


más que un índice, que se encuentra en una tabla del sistema
operativo llamada tabla de archivos abiertos

7
El tipo FILE *
El tipo FILE es una estructura definida en stdio.h que
contiene información para procesar el archivo

Esta estructura contiene un descriptor de archivo, que no es


más que un índice, que se encuentra en una tabla del sistema
operativo llamada tabla de archivos abiertos

Cada elemento de esa tabla contiene un FCB (bloque de


control de archivo) que es lo que utiliza el SO para administrar
el archivo

7
El tipo FILE *

8
El tipo FILE *
El usuario tiene acceso a esto Solo el SO tiene acceso a esto

Tabla de archivos abiertos

fopen devuelve un puntero a una estructura FILE

La estructura FILE para "clients.dat" contiene un descripor


(un entero que es el índice de la tabla de archivos abiertos)

para

Cuando el programa prepara una llamada


de lectura o escrituro como

el programa localiza el descriptor (el 7) El programa llama a un servicio del SO que usa
en la estructura FILE y lo utiliza para localizar los datos del FCB para controlar la lectura y escritura
el FCB en la tabla de archivos abiertos hacia el archivo en el disco. El usuario no puede acceder
al FCB directamente.

Esta entrada es copiada desde el FCB


cuando el archivo es abierto.

8
Apertura y cierre de streams

9
Apertura y cierre de streams
Las funciones utilizadas para abrir y cerrar archivos son fopen
y fclose

9
Apertura y cierre de streams
Las funciones utilizadas para abrir y cerrar archivos son fopen
y fclose

fopen
FILE * fopen (const char *filename, const char *opentype);

9
Apertura y cierre de streams
Las funciones utilizadas para abrir y cerrar archivos son fopen
y fclose

fopen
FILE * fopen (const char *filename, const char *opentype);

fopen recibe dos cadenas como argumentos: el nombre del


archivo y el modo de apertura.

9
Apertura y cierre de streams
Las funciones utilizadas para abrir y cerrar archivos son fopen
y fclose

fopen
FILE * fopen (const char *filename, const char *opentype);

fopen recibe dos cadenas como argumentos: el nombre del


archivo y el modo de apertura.

Devuelve un FILE * que representa al stream asociado al


archivo o NULL ante un error.

9
Apertura y cierre de streams
Las funciones utilizadas para abrir y cerrar archivos son fopen
y fclose

10
Apertura y cierre de streams
Las funciones utilizadas para abrir y cerrar archivos son fopen
y fclose

fclose
int fclose (FILE *stream);

10
Apertura y cierre de streams
Las funciones utilizadas para abrir y cerrar archivos son fopen
y fclose

fclose
int fclose (FILE *stream);

fclose recibe el FILE * del stream asociado al archivo que se


quiere cerrar.

10
Apertura y cierre de streams
Las funciones utilizadas para abrir y cerrar archivos son fopen
y fclose

fclose
int fclose (FILE *stream);

fclose recibe el FILE * del stream asociado al archivo que se


quiere cerrar.

Devuelve un 0 (cero) si tuvo éxito, o un EOF si falló.

10
Apertura y cierre de streams

11
Apertura y cierre de streams
Según el estándar los archivos pueden ser abiertos en modo
texto o en modo binario, para lectura, escritura o ambos.

11
Apertura y cierre de streams
Según el estándar los archivos pueden ser abiertos en modo
texto o en modo binario, para lectura, escritura o ambos.

Los modos de apertura son:

r para lectura en modo texto

11
Apertura y cierre de streams
Según el estándar los archivos pueden ser abiertos en modo
texto o en modo binario, para lectura, escritura o ambos.

Los modos de apertura son:

r para lectura en modo texto


w para escritura en modo texto. Si no existe lo crea. Si
existe lo sobrescribe.

11
Apertura y cierre de streams
Según el estándar los archivos pueden ser abiertos en modo
texto o en modo binario, para lectura, escritura o ambos.

Los modos de apertura son:

r para lectura en modo texto


w para escritura en modo texto. Si no existe lo crea. Si
existe lo sobrescribe.
a para escritura en modo texto. Si no existe lo crea. Si
existe escribe al final.

11
Apertura y cierre de streams

12
Apertura y cierre de streams
Otros modos de apertura son:

r+ para lectura y escritura en modo texto. El archivo debe


existir.

12
Apertura y cierre de streams
Otros modos de apertura son:

r+ para lectura y escritura en modo texto. El archivo debe


existir.
w+ para lectura y escritura en modo texto. Si no existe lo
crea. Si existe lo sobrescribe.

12
Apertura y cierre de streams
Otros modos de apertura son:

r+ para lectura y escritura en modo texto. El archivo debe


existir.
w+ para lectura y escritura en modo texto. Si no existe lo
crea. Si existe lo sobrescribe.
a+ para lectura y escritura en modo texto. Si no existe lo
crea. Siempre escribe al final.

12
Apertura y cierre de streams

13
Apertura y cierre de streams
En modo binario existen los mismos modos, agregando
después de la letra inicial una b

13
Apertura y cierre de streams
En modo binario existen los mismos modos, agregando
después de la letra inicial una b

rb
wb
ab
rb+
wb+
ab+

14
Apertura y cierre de streams

15
Apertura y cierre de streams
Ejemplo de redirección de stdout a un archivo

15
Apertura y cierre de streams
Ejemplo de redirección de stdout a un archivo
#include <stdio.h>
int main (void)
{
fclose(stdout);
stdout = fopen("salida.txt", "w");
printf("Hola, mundo!\n");
return 0;
}

15
Apertura y cierre de streams
Ejemplo de redirección de stdout a un archivo
#include <stdio.h>
int main (void)
{
fclose(stdout);
stdout = fopen("salida.txt", "w");
printf("Hola, mundo!\n");
return 0;
}

fclose cierra el stream estándar stdout

15
Apertura y cierre de streams
Ejemplo de redirección de stdout a un archivo
#include <stdio.h>
int main (void)
{
fclose(stdout);
stdout = fopen("salida.txt", "w");
printf("Hola, mundo!\n");
return 0;
}

15
Apertura y cierre de streams
Ejemplo de redirección de stdout a un archivo
#include <stdio.h>
int main (void)
{
fclose(stdout);
stdout = fopen("salida.txt", "w");
printf("Hola, mundo!\n");
return 0;
}

fopen abre el archivo salida.txt en modo escritura

15
Apertura y cierre de streams
Ejemplo de redirección de stdout a un archivo
#include <stdio.h>
int main (void)
{
fclose(stdout);
stdout = fopen("salida.txt", "w");
printf("Hola, mundo!\n");
return 0;
}

fopen abre el archivo salida.txt en modo escritura, y el


stream asociado es asignado en stdout. Si el archivo no
existe, lo crea.

15
Apertura y cierre de streams
Ejemplo de redirección de stdout a un archivo
#include <stdio.h>
int main (void)
{
fclose(stdout);
stdout = fopen("salida.txt", "w");
printf("Hola, mundo!\n");
return 0;
}

15
Apertura y cierre de streams
Ejemplo de redirección de stdout a un archivo
#include <stdio.h>
int main (void)
{
fclose(stdout);
stdout = fopen("salida.txt", "w");
printf("Hola, mundo!\n");
return 0;
}

Luego de compilar, la ejecución no muestra nada por pantalla

15
Apertura y cierre de streams
Ejemplo de redirección de stdout a un archivo
#include <stdio.h>
int main (void)
{
fclose(stdout);
stdout = fopen("salida.txt", "w");
printf("Hola, mundo!\n");
return 0;
}

15
Apertura y cierre de streams
Ejemplo de redirección de stdout a un archivo
#include <stdio.h>
int main (void)
{
fclose(stdout);
stdout = fopen("salida.txt", "w");
printf("Hola, mundo!\n");
return 0;
}

$ gcc -Wall -std=c99 -pedantic-errors u10-redirect-stdout.c


$

15
Apertura y cierre de streams
Ejemplo de redirección de stdout a un archivo
#include <stdio.h>
int main (void)
{
fclose(stdout);
stdout = fopen("salida.txt", "w");
printf("Hola, mundo!\n");
return 0;
}

$ gcc -Wall -std=c99 -pedantic-errors u10-redirect-stdout.c


$ ./a.out
$

15
Apertura y cierre de streams
Ejemplo de redirección de stdout a un archivo
#include <stdio.h>
int main (void)
{
fclose(stdout);
stdout = fopen("salida.txt", "w");
printf("Hola, mundo!\n");
return 0;
}

$ gcc -Wall -std=c99 -pedantic-errors u10-redirect-stdout.c


$ ./a.out
$

pero si se revisa el contenido del archivo salida.txt...

15
Apertura y cierre de streams
Ejemplo de redirección de stdout a un archivo
#include <stdio.h>
int main (void)
{
fclose(stdout);
stdout = fopen("salida.txt", "w");
printf("Hola, mundo!\n");
return 0;
}

$ gcc -Wall -std=c99 -pedantic-errors u10-redirect-stdout.c


$ ./a.out
$

15
Apertura y cierre de streams
Ejemplo de redirección de stdout a un archivo
#include <stdio.h>
int main (void)
{
fclose(stdout);
stdout = fopen("salida.txt", "w");
printf("Hola, mundo!\n");
return 0;
}

$ gcc -Wall -std=c99 -pedantic-errors u10-redirect-stdout.c


$ ./a.out
$ cat salida.txt
Hola, mundo!
$

15
Lectura de streams

16
Lectura de streams
Descontando las funciones usadas para leer desde stdin, las
funciones usadas para leer desde un archivo en general,
disponibles en stdio.h según el estándar son:

16
Lectura de streams
Descontando las funciones usadas para leer desde stdin, las
funciones usadas para leer desde un archivo en general,
disponibles en stdio.h según el estándar son:

fgetc
int fgetc ( FILE * stream );

16
Lectura de streams
Descontando las funciones usadas para leer desde stdin, las
funciones usadas para leer desde un archivo en general,
disponibles en stdio.h según el estándar son:

fgetc
int fgetc ( FILE * stream );

Toma un caracter desde el archivo representado por el stream


stream y lo devuelve como int

16
Lectura de streams
Descontando las funciones usadas para leer desde stdin, las
funciones usadas para leer desde un archivo en general,
disponibles en stdio.h según el estándar son:

16
Lectura de streams
Descontando las funciones usadas para leer desde stdin, las
funciones usadas para leer desde un archivo en general,
disponibles en stdio.h según el estándar son:

fgets
char *fgets(char *str, int n, FILE *stream);

16
Lectura de streams
Descontando las funciones usadas para leer desde stdin, las
funciones usadas para leer desde un archivo en general,
disponibles en stdio.h según el estándar son:

fgets
char *fgets(char *str, int n, FILE *stream);

Toma una cantidad n de caracteres desde el archivo


representado por el stream stream y lo guarda en el arreglo
apuntado por el puntero str

16
Lectura de streams
Descontando las funciones usadas para leer desde stdin, las
funciones usadas para leer desde un archivo en general,
disponibles en stdio.h según el estándar son:

16
Lectura de streams
Descontando las funciones usadas para leer desde stdin, las
funciones usadas para leer desde un archivo en general,
disponibles en stdio.h según el estándar son:

fscanf
int fscanf(FILE *stream, const char *format, ...);

16
Lectura de streams
Descontando las funciones usadas para leer desde stdin, las
funciones usadas para leer desde un archivo en general,
disponibles en stdio.h según el estándar son:

fscanf
int fscanf(FILE *stream, const char *format, ...);

Exactamente igual al scanf que se usa con stdin (desde el


teclado) pero lleva como primer argumento el stream de
donde se toman los valores

16
Lectura de streams

17
Lectura de streams
Si se tiene un archivo de texto llamado frutas.txt

17
Lectura de streams
Si se tiene un archivo de texto llamado frutas.txt

$ cat frutas.txt
manzana
banana
naranja
pera
$

17
Lectura de streams

18
Lectura de streams
#include <stdio.h>
int main (void)
{
FILE * fp;
char cadena[80] = {0};
fp = fopen("frutas.txt", "r");
if ( fp == NULL ) {
printf("No se pudo abrir...\n");
return 1;
}
fgets(cadena, 80, fp);
printf("%s\n", cadena);
fclose(fp);
return 0;
}

18
Lectura de streams
#include <stdio.h>
fopen devuelve NULL
int main (void)
{ si el archivo no
FILE * fp;
char cadena[80] = {0}; puede abrirse por
fp = fopen("frutas.txt", "r");
if ( fp == NULL ) {
algún motivo
printf("No se pudo abrir...\n");
return 1;
}
fgets(cadena, 80, fp);
printf("%s\n", cadena);
fclose(fp);
return 0;
}

18
Lectura de streams
#include <stdio.h>
int main (void)
{
FILE * fp;
char cadena[80] = {0};
fp = fopen("frutas.txt", "r");
if ( fp == NULL ) {
printf("No se pudo abrir...\n");
return 1;
}
fgets(cadena, 80, fp);
printf("%s\n", cadena);
fclose(fp);
return 0;
}

18
Lectura de streams
#include <stdio.h>
int main (void)
{
FILE * fp;
char cadena[80] = {0};
fp = fopen("frutas.txt", "r");
if ( fp == NULL ) {
printf("No se pudo abrir...\n");
return 1;
}
fgets(cadena, 80, fp);
printf("%s\n", cadena);
fclose(fp);
return 0;
}

18
Lectura de streams
#include <stdio.h>
debe chequearse la
int main (void)
{ correcta apertura
FILE * fp;
char cadena[80] = {0}; para evitar errores
fp = fopen("frutas.txt", "r");
if ( fp == NULL ) {
en tiempo de
printf("No se pudo abrir...\n");
return 1;
ejecución
}
fgets(cadena, 80, fp);
printf("%s\n", cadena);
fclose(fp);
return 0;
}

18
Lectura de streams
#include <stdio.h>
int main (void)
{
FILE * fp;
char cadena[80] = {0};
fp = fopen("frutas.txt", "r");
if ( fp == NULL ) {
printf("No se pudo abrir...\n");
return 1;
}
fgets(cadena, 80, fp);
printf("%s\n", cadena);
fclose(fp);
return 0;
}

18
Lectura de streams
#include <stdio.h>
int main (void)
{
FILE * fp;
char cadena[80] = {0};
fp = fopen("frutas.txt", "r");
if ( fp == NULL ) {
printf("No se pudo abrir...\n");
return 1;
}
fgets(cadena, 80, fp);
printf("%s\n", cadena);
fclose(fp);
return 0;
}

18
Lectura de streams
#include <stdio.h>
fgets toma hasta
int main (void)
{ 79 (80-1)
FILE * fp;
char cadena[80] = {0}; caracteres. Si
fp = fopen("frutas.txt", "r");
if ( fp == NULL ) {
encuentra un
printf("No se pudo abrir...\n");
return 1;
retorno de línea (\n)
} termina
fgets(cadena, 80, fp);
printf("%s\n", cadena);
fclose(fp);
return 0;
}

18
Lectura de streams

19
Lectura de streams
se puede reemplazar la línea

fgets(cadena, 80, fp);

19
Lectura de streams
se puede reemplazar la línea

fgets(cadena, 80, fp);

...por

fscanf(fp, "%80[^\n]s", cadena);

19
Lectura de streams
se puede reemplazar la línea

fgets(cadena, 80, fp);

...por

fscanf(fp, "%80[^\n]s", cadena);

La entrada fscanf es formateada, a diferencia de fgets que


solo lee cadenas de texto.

19
Lectura de streams
se puede reemplazar la línea

fgets(cadena, 80, fp);

...por

fscanf(fp, "%80[^\n]s", cadena);

La entrada fscanf es formateada, a diferencia de fgets que


solo lee cadenas de texto.

Con fscanf se pueden leer números enteros o reales


directamente desde el archivo.

19
Lectura de streams

20
Lectura de streams
Para leer más líneas se pueden usar sucesivos fscanf o fgets
o utilizar estructuras repetitivas

fgets(cadena, 80, fp);


while (!feof(fp)) {
printf("%s", cadena);
fgets(cadena, 80, fp);
}

20
Lectura de streams
Para leer más líneas se pueden usar sucesivos fscanf o fgets
o utilizar estructuras repetitivas

fgets(cadena, 80, fp);


while (!feof(fp)) {
printf("%s", cadena);
fgets(cadena, 80, fp);
}

La función feof devuelve 0 (cero) si no se alcanzó el final del


archivo.

20
Lectura de streams
Para leer más líneas se pueden usar sucesivos fscanf o fgets
o utilizar estructuras repetitivas

fgets(cadena, 80, fp);


while (!feof(fp)) {
printf("%s", cadena);
fgets(cadena, 80, fp);
}

La función feof devuelve 0 (cero) si no se alcanzó el final del


archivo.

Devuelve 1 (uno) luego de intentar leer datos del archivo sin


lograrlo por estar al final del mismo.

20
Escritura de streams

21
Escritura de streams
Las funciones usadas para escribir en un archivo de texto,
disponibles en stdio.h según el estándar son:

21
Escritura de streams
Las funciones usadas para escribir en un archivo de texto,
disponibles en stdio.h según el estándar son:

fputc
int fputc(int data, FILE * stream);

21
Escritura de streams
Las funciones usadas para escribir en un archivo de texto,
disponibles en stdio.h según el estándar son:

fputc
int fputc(int data, FILE * stream);

Toma el dato data, lo convierte a unsigned char y lo escribe


en la salida apuntada por stream. En caso de éxito devuelve el
caracter escrito, si no, devuelve EOF.

21
Escritura de streams
Las funciones usadas para escribir en un archivo de texto,
disponibles en stdio.h según el estándar son:

21
Escritura de streams
Las funciones usadas para escribir en un archivo de texto,
disponibles en stdio.h según el estándar son:

fputs
int fputs(const char * ps, FILE * stream);

22
Escritura de streams
Las funciones usadas para escribir en un archivo de texto,
disponibles en stdio.h según el estándar son:

fputs
int fputs(const char * ps, FILE * stream);

Toma la cadena apuntada por el puntero ps, y la escribe en la


salida apuntada por stream hasta que encuentra un caracter
nulo. En caso de éxito devuelve un entero mayor a cero, si no,
devuelve EOF.

22
Escritura de streams
Las funciones usadas para escribir en un archivo de texto,
disponibles en stdio.h según el estándar son:

23
Escritura de streams
Las funciones usadas para escribir en un archivo de texto,
disponibles en stdio.h según el estándar son:

fprintf
int fprintf(FILE * stream, const char * format, ...);

23
Escritura de streams
Las funciones usadas para escribir en un archivo de texto,
disponibles en stdio.h según el estándar son:

fprintf
int fprintf(FILE * stream, const char * format, ...);

Exactamente igual al printf que se usa con stdout (a la


pantalla) pero lleva como primer argumento el stream donde
se colocan los valores. Tiene la ventaja de dar formato a la
salida.

23
Ejemplo Lectura/Escritura de streams

24
Ejemplo Lectura/Escritura de streams
#include <stdio.h>
void agregar(FILE *);
void mostrar(FILE *);
void menu (FILE *);
int menu_option (void);
int main (void) {
FILE *fp;
fp = fopen("db.txt","a+");
menu(fp);
fclose(fp);
return 0;
}

24
Ejemplo Lectura/Escritura de streams
#include <stdio.h>
void agregar(FILE *);
void mostrar(FILE *);
void menu (FILE *);
int menu_option (void);
int main (void) {
FILE *fp;
fp = fopen("db.txt","a+");
menu(fp);
fclose(fp);
return 0;
}

24
Ejemplo Lectura/Escritura de streams
#include <stdio.h>
void agregar(FILE *);
void mostrar(FILE *);
void menu (FILE *);
int menu_option (void);
int main (void) {
FILE *fp;
fp = fopen("db.txt","a+");
menu(fp);
fclose(fp);
return 0;
}

El modo "a+" permite agregar registros al final del archivo y


al mismo tiempo leer.

24
Ejemplo Lectura/Escritura de streams

24
Ejemplo Lectura/Escritura de streams
void menu (FILE *fp)
{
int salir = 0;
int op;
do {
op = menu_option();
switch (op) {
case 1:
agregar(fp);
break;
case 2:
mostrar(fp);
break;
case 3:
salir = 1;
break;
default:
printf("Opción no válida\n");
}
} while ( salir == 0 );
}

24
Ejemplo Lectura/Escritura de streams

24
Ejemplo Lectura/Escritura de streams
int menu_option (void)
{
int op;
printf("1-Agregar\n");
printf("2-Mostrar\n");
printf("3-Salir\n");
printf("Que quiere? "); scanf("%d", &op);
return op;
}

24
Ejemplo Lectura/Escritura de streams

24
Ejemplo Lectura/Escritura de streams
void agregar(FILE *fp)
{
int legajo;
char nombre[80];
char apellido[80];
printf("Ingrese el nombre: "); scanf(" %80[^\n]s", nombre);
printf("Ingrese el apellido: "); scanf(" %80[^\n]s", apellido);
printf("Ingrese el legajo: "); scanf("%d", &legajo);
fprintf(fp, "%d %s, %s\n", legajo, apellido, nombre);
}

24
Ejemplo Lectura/Escritura de streams
void agregar(FILE *fp)
{
int legajo;
char nombre[80];
char apellido[80];
printf("Ingrese el nombre: "); scanf(" %80[^\n]s", nombre);
printf("Ingrese el apellido: "); scanf(" %80[^\n]s", apellido);
printf("Ingrese el legajo: "); scanf("%d", &legajo);
fprintf(fp, "%d %s, %s\n", legajo, apellido, nombre);
}

24
Ejemplo Lectura/Escritura de streams
void agregar(FILE *fp)
{
int legajo;
char nombre[80];
char apellido[80];
printf("Ingrese el nombre: "); scanf(" %80[^\n]s", nombre);
printf("Ingrese el apellido: "); scanf(" %80[^\n]s", apellido);
printf("Ingrese el legajo: "); scanf("%d", &legajo);
fprintf(fp, "%d %s, %s\n", legajo, apellido, nombre);
}

La función fprintf agrega el registro al final (debido al a+ del


fopen)

24
Ejemplo Lectura/Escritura de streams

24
Ejemplo Lectura/Escritura de streams
void mostrar(FILE *fp)
{
char linea[160];
rewind(fp);
fgets(linea, 160, fp);
while (!feof(fp)) {
fputs(linea, stdout);
fgets(linea, 160, fp);
}
}

24
Ejemplo Lectura/Escritura de streams
void mostrar(FILE *fp)
{
char linea[160];
rewind(fp);
fgets(linea, 160, fp);
while (!feof(fp)) {
fputs(linea, stdout);
fgets(linea, 160, fp);
}
}

24
Ejemplo Lectura/Escritura de streams
void mostrar(FILE *fp)
{
char linea[160];
rewind(fp);
fgets(linea, 160, fp);
while (!feof(fp)) {
fputs(linea, stdout);
fgets(linea, 160, fp);
}
}

La función rewind vuelve al inicio al puntero que indica cual es


la posición que se lee en el archivo.

24
Archivos binarios

25
Archivos binarios
La diferencia entre los archivos de texto y los binarios es que
los primeros siempre usan caracteres para representar la
información, aunque sean números.

25
Archivos binarios
La diferencia entre los archivos de texto y los binarios es que
los primeros siempre usan caracteres para representar la
información, aunque sean números.

Los binarios escriben en los archivos con bits, sin importar lo


que representen esos bits.

25
Archivos binarios
La diferencia entre los archivos de texto y los binarios es que
los primeros siempre usan caracteres para representar la
información, aunque sean números.

Los binarios escriben en los archivos con bits, sin importar lo


que representen esos bits.

En cuestiones de espacio, a veces puede ser una ventaja

25
Archivos binarios

26
Archivos binarios
La función usada para escribir en un archivo binario,
disponible en stdio.h según el estándar es:

26
Archivos binarios
La función usada para escribir en un archivo binario,
disponible en stdio.h según el estándar es:

fwrite
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

26
Archivos binarios
La función usada para escribir en un archivo binario,
disponible en stdio.h según el estándar es:

fwrite
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

Escribe en el stream apuntado por stream, nmemb datos de


tamaño size comenzando por la posición de memoria
apuntada por ptr.

26
Archivos binarios

27
Archivos binarios
FILE * fpt;
FILE * fpb;
int numero = 4000000;
fpt = fopen("archivo.txt", "w");
fpb = fopen("archivo.bin", "wb");
fprintf(fpt, "%d", numero);
fwrite(&numero, sizeof(numero), 1, fpb);
fclose(fpb);
fclose(fpt);

27
Archivos binarios
FILE * fpt;
FILE * fpb;
int numero = 4000000;
fpt = fopen("archivo.txt", "w");
fpb = fopen("archivo.bin", "wb");
fprintf(fpt, "%d", numero);
fwrite(&numero, sizeof(numero), 1, fpb);
fclose(fpb);
fclose(fpt);

27
Archivos binarios
FILE * fpt;
FILE * fpb;
int numero = 4000000;
fpt = fopen("archivo.txt", "w");
fpb = fopen("archivo.bin", "wb");
fprintf(fpt, "%d", numero);
fwrite(&numero, sizeof(numero), 1, fpb);
fclose(fpb);
fclose(fpt);

si se graba en archivo.txt en modo texto la variable numero,


se graban siete caracteres (un 4 y seis 0) lo que corresponden
a siete bytes.

27
Archivos binarios
FILE * fpt;
FILE * fpb;
int numero = 4000000;
fpt = fopen("archivo.txt", "w");
fpb = fopen("archivo.bin", "wb");
fprintf(fpt, "%d", numero);
fwrite(&numero, sizeof(numero), 1, fpb);
fclose(fpb);
fclose(fpt);

27
Archivos binarios
FILE * fpt;
FILE * fpb;
int numero = 4000000;
fpt = fopen("archivo.txt", "w");
fpb = fopen("archivo.bin", "wb");
fprintf(fpt, "%d", numero);
fwrite(&numero, sizeof(numero), 1, fpb);
fclose(fpb);
fclose(fpt);

27
Archivos binarios
FILE * fpt;
FILE * fpb;
int numero = 4000000;
fpt = fopen("archivo.txt", "w");
fpb = fopen("archivo.bin", "wb");
fprintf(fpt, "%d", numero);
fwrite(&numero, sizeof(numero), 1, fpb);
fclose(fpb);
fclose(fpt);

si se graba en archivo.bin en modo binario la variable


numero, se graban cuatro bytes que corresponden a un int

27
Archivos binarios
FILE * fpt;
FILE * fpb;
int numero = 4000000;
fpt = fopen("archivo.txt", "w");
fpb = fopen("archivo.bin", "wb");
fprintf(fpt, "%d", numero);
fwrite(&numero, sizeof(numero), 1, fpb);
fclose(fpb);
fclose(fpt);

27
Archivos binarios
FILE * fpt;
FILE * fpb;
int numero = 4000000;
fpt = fopen("archivo.txt", "w");
fpb = fopen("archivo.bin", "wb");
fprintf(fpt, "%d", numero);
fwrite(&numero, sizeof(numero), 1, fpb);
fclose(fpb);
fclose(fpt);

$ ls -lh archivo.*
-rw-rw-r-- 1 claudiojpaz claudiojpaz 4 oct 20 19:23 archivo.bin
-rw-rw-r-- 1 claudiojpaz claudiojpaz 7 oct 20 19:23 archivo.txt
$

27
Archivos binarios
FILE * fpt;
FILE * fpb;
int numero = 4000000;
fpt = fopen("archivo.txt", "w");
fpb = fopen("archivo.bin", "wb");
fprintf(fpt, "%d", numero);
fwrite(&numero, sizeof(numero), 1, fpb);
fclose(fpb);
fclose(fpt);

$ ls -lh archivo.*
-rw-rw-r-- 1 claudiojpaz claudiojpaz 4 oct 20 19:23 archivo.bin
-rw-rw-r-- 1 claudiojpaz claudiojpaz 7 oct 20 19:23 archivo.txt
$

27
Archivos binarios

28
Archivos binarios
FILE * fpt;
FILE * fpb;
char cadena[80] = "Texto Vs Binario";
fpt = fopen("archivo.txt", "w");
fpb = fopen("archivo.bin", "wb");
fprintf(fpt, "%s", cadena);
fwrite(cadena, sizeof(cadena), 1, fpb);
fclose(fpb);
fclose(fpt);

28
Archivos binarios
FILE * fpt;
FILE * fpb;
char cadena[80] = "Texto Vs Binario";
fpt = fopen("archivo.txt", "w");
fpb = fopen("archivo.bin", "wb");
fprintf(fpt, "%s", cadena);
fwrite(cadena, sizeof(cadena), 1, fpb);
fclose(fpb);
fclose(fpt);

$ ls -lh archivo.*
-rw-rw-r-- 1 claudiojpaz claudiojpaz 80 oct 20 23:37 archivo.bin
-rw-rw-r-- 1 claudiojpaz claudiojpaz 16 oct 20 23:37 archivo.txt
$

28
Archivos binarios
FILE * fpt;
FILE * fpb;
char cadena[80] = "Texto Vs Binario";
fpt = fopen("archivo.txt", "w");
fpb = fopen("archivo.bin", "wb");
fprintf(fpt, "%s", cadena);
fwrite(cadena, sizeof(cadena), 1, fpb);
fclose(fpb);
fclose(fpt);

$ ls -lh archivo.*
-rw-rw-r-- 1 claudiojpaz claudiojpaz 80 oct 20 23:37 archivo.bin
-rw-rw-r-- 1 claudiojpaz claudiojpaz 16 oct 20 23:37 archivo.txt
$

28
Archivos binarios
FILE * fpt;
FILE * fpb;
char cadena[80] = "Texto Vs Binario";
fpt = fopen("archivo.txt", "w");
fpb = fopen("archivo.bin", "wb");
fprintf(fpt, "%s", cadena);
fwrite(cadena, sizeof(cadena), 1, fpb);
fclose(fpb);
fclose(fpt);

$ ls -lh archivo.*
-rw-rw-r-- 1 claudiojpaz claudiojpaz 80 oct 20 23:37 archivo.bin
-rw-rw-r-- 1 claudiojpaz claudiojpaz 16 oct 20 23:37 archivo.txt
$

El archivo binario almacena la cadena completa

28
Archivos binarios

29
Archivos binarios
La ventaja principal del uso de archivos en modo binario es
que cada registro ocupa largo fijo.

29
Archivos binarios
La ventaja principal del uso de archivos en modo binario es
que cada registro ocupa largo fijo.

Entonces se puede accesar a los datos del archivo de manera


aleatoria, porque se puede calcular donde comienza cada
dato.

29
Archivos binarios
La ventaja principal del uso de archivos en modo binario es
que cada registro ocupa largo fijo.

Entonces se puede accesar a los datos del archivo de manera


aleatoria, porque se puede calcular donde comienza cada
dato.

Además como la información se almacena byte a byte, se


pueden guardar datos más complejos, como estructuras de
datos.

29
Archivos binarios

30
Archivos binarios
La función usada para leer de un archivo binario, disponible en
stdio.h según el estándar es:

30
Archivos binarios
La función usada para leer de un archivo binario, disponible en
stdio.h según el estándar es:

fread
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

30
Archivos binarios
La función usada para leer de un archivo binario, disponible en
stdio.h según el estándar es:

fread
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

Lee del stream apuntado por stream, nmemb datos de tamaño


size y los pone en la posición de memoria apuntada por ptr.

30
Archivos binarios

31
Archivos binarios
La otra función más usada en un archivo binario, disponible en
stdio.h según el estándar es:

31
Archivos binarios
La otra función más usada en un archivo binario, disponible en
stdio.h según el estándar es:

fseek
int fseek(FILE *stream, long int offset, int whence);

31
Archivos binarios
La otra función más usada en un archivo binario, disponible en
stdio.h según el estándar es:

fseek
int fseek(FILE *stream, long int offset, int whence);

Mueve el puntero de posición dentro del archivo apuntado por


stream una distancia dada por offset. El argumento whence
indica desde donde se hace el movimiento del offset.

31
Archivos binarios
La otra función más usada en un archivo binario, disponible en
stdio.h según el estándar es:

fseek
int fseek(FILE *stream, long int offset, int whence);

31
Archivos binarios
La otra función más usada en un archivo binario, disponible en
stdio.h según el estándar es:

fseek
int fseek(FILE *stream, long int offset, int whence);

SEEK_SET desde el principio del archivo

SEEK_CUR desde la posición actual

SEEK_END desde el final

31
Acceso aleatorio

32
Acceso aleatorio
Supongamos que queremos llevar una base de datos con 10
estudiantes, donde cada uno cuenta con un código, un
nombre y una nota.

32
Acceso aleatorio
Supongamos que queremos llevar una base de datos con 10
estudiantes, donde cada uno cuenta con un código, un
nombre y una nota.

Podemos aprovechar una estructura como la que sigue

struct estudiante {
int cod;
char nombre[40];
int nota;
};

32
Acceso aleatorio
Supongamos que queremos llevar una base de datos con 10
estudiantes, donde cada uno cuenta con un código, un
nombre y una nota.

Podemos aprovechar una estructura como la que sigue

struct estudiante {
int cod;
char nombre[40];
int nota;
};

Si la usamos en un archivo en modo binario cada registro será


de 48 bytes

32
Acceso aleatorio

33
Acceso aleatorio
Primero se crea un archivo en modo binario

33
Acceso aleatorio
Primero se crea un archivo en modo binario

FILE *fp;
fp = fopen("base.bin", "wb");

33
Acceso aleatorio
Primero se crea un archivo en modo binario

FILE *fp;
fp = fopen("base.bin", "wb");

Recordar chequear que haya sido creado con éxito

33
Acceso aleatorio

34
Acceso aleatorio
Luego con fwrite se escriben los 10 registros (o los que se
necesiten) para almacenar los estudiantes

34
Acceso aleatorio
Luego con fwrite se escriben los 10 registros (o los que se
necesiten) para almacenar los estudiantes

for (int i = 0 ; i < N; i++) {


est_cero.cod = i;
fwrite(&est_cero, sizeof(struct estudiante), 1, fp);
}

34
Acceso aleatorio
Luego con fwrite se escriben los 10 registros (o los que se
necesiten) para almacenar los estudiantes

for (int i = 0 ; i < N; i++) {


est_cero.cod = i;
fwrite(&est_cero, sizeof(struct estudiante), 1, fp);
}

Para identificar cada registro, se usará un número único,


cargado desde el comienzo (en este caso usando la variable i)

34
Acceso aleatorio

35
Acceso aleatorio
Para leer todos los registros se puede obtener un bloque
completo (los 10 registros) y luego recorrer el arreglo en
memoria

FILE *fpb;
struct estudiante e[10] = {0};
fpb = fopen("archivo.bin", "rb");
fread(e, sizeof(struct estudiante), 10, fpb);
for (int i = 0; i < 10; i++)
printf("%d %s %d\n", e[i].legajo, e[i].nombre, e[i].nota);
fclose(fpb);

35
Acceso aleatorio

36
Acceso aleatorio
Para leer solo un registro en particular se usa fseek

FILE *fpb;
struct estudiante e = {0};
int n;
fpb = fopen("archivo.bin", "rb+");
printf("Que registro quiere ver? ");
scanf("%d", &n);
fseek(fpb, n*sizeof(struct estudiante), SEEK_SET);
fread(&e, sizeof(struct estudiante), 1, fpb);
printf("%d %s %d\n", e.legajo, e.nombre, e.nota);
fclose(fpb);

36
Acceso aleatorio

37
Acceso aleatorio
También con fseek se puede posicionar para cambiar un
registro en particular

struct estudiante e = {0};


int n;
FILE *fpb = fopen("archivo.bin", "rb+");
printf("Que registro quiere cambiar? ");
scanf("%d", &n);
fseek(fpb, n*sizeof(struct estudiante), SEEK_SET);
fread(&e, sizeof(struct estudiante), 1, fpb);
e.nota = 8;
fseek(fpb, n*sizeof(struct estudiante), SEEK_SET);
fwrite(&e, sizeof(struct estudiante), 1, fpb);
fclose(fpb);

37
Acceso aleatorio

38
Acceso aleatorio
Una vez que se lee la estructura, luego de modificarla hay que
volver a colocarla en el archivo para que queden registrados
los cambios.

38
Acceso aleatorio
Una vez que se lee la estructura, luego de modificarla hay que
volver a colocarla en el archivo para que queden registrados
los cambios.

Para esto hay que volver a posicionarse en el registro correcto


con fseek y realizar el fwrite

38

También podría gustarte