• Lunes 16 de Diciembre de 2024, 01:39

Autor Tema:  Leer Archivos Binarios  (Leído 4008 veces)

JrcsDev

  • Miembro MUY activo
  • ***
  • Mensajes: 245
  • Nacionalidad: ve
    • Ver Perfil
    • http://codigo7.wordpress.com/
Leer Archivos Binarios
« en: Jueves 29 de Junio de 2006, 18:15 »
0
Saludos amigos... Hice un programa que guarda una estructura en un archivo binario. Creo que eso funciona perfectamente... Aquí les dejo el código

Código: Text
  1. #include<conio.h>
  2. #include<stdio.h>
  3. #include<string.h>
  4. #define nomar "chumon.txt"
  5. typedef struct persona
  6. {  char nombre[10],apellido[10],edad[3];
  7. };
  8. FILE *f;
  9. persona p,p1;
  10. int nr;
  11. char nom[10],ape[10],ed[3];
  12. void main()
  13. {   clrscr();
  14.      gotoxy(2,2);printf("Nombre: ");
  15.      scanf("%10s", &nom);
  16.      gotoxy(2,4);printf("Apellido: ");
  17.      scanf("%10s", &ape);
  18.      gotoxy(2,6);printf("Edad: ");
  19.      scanf("%3s", &ed);
  20.      if ((f=fopen(nomar,"rb"))==NULL)
  21.      {  f=fopen(nomar,"wb");
  22.      }
  23.      else
  24.      {  f=fopen(nomar,"a+b");
  25.      }
  26.      strcpy(p.nombre,nom);
  27.      strcpy(p.apellido,ape);
  28.      strcpy(p.edad,ed);
  29.      fwrite(&p, sizeof(p), 1, f);
  30.      fclose(f);
  31.      getch();
  32. }
  33.  


El problema creo que está cuando trato de recuperar la información del archivo. El código que hice es este, pero  no se si funciona bien... Si alguien puede ayudarme y decirme qué estoy haciendo mal, se lo agradezco desde ya... Este es el código:

Código: Text
  1. #include<conio.h>
  2. #include<stdio.h>
  3. #include<string.h>
  4. #define nomar "chumon.txt"
  5. typedef struct persona
  6. {  char nombre[10],apellido[10],edad[3];
  7. };
  8. FILE *f;
  9. persona p1;
  10. int nr;
  11. char nom[10],ape[10],ed[3];
  12. void main()
  13. {   clrscr();
  14.      f=fopen(nomar,"wb");
  15.      while (fread(&p1, sizeof(persona), 1, f))
  16.      {  printf("\n%s",p1.nombre);
  17.      }
  18.      fclose(f);
  19.      getch();
  20. }
  21.  

No entiendo bien lo del fread(), espero por su ayuda amigos. Gracias! xD
Sígueme en Twitter]
Donar comida a los chicos necesitados!
Todo lo puedo en Cristo que me fortalece...

Diodo

  • Moderador
  • ******
  • Mensajes: 658
    • Ver Perfil
    • http://www.solocodigo.com
Re: Leer Archivos Binarios
« Respuesta #1 en: Jueves 29 de Junio de 2006, 18:24 »
0
En el segundo codigo

Código: Text
  1.  
  2. f=fopen(nomar,"wb");
  3.  
  4.  

Tienes que poner rb (abrir el fichero para leer), en vez de wb (abrir el fichero para escribir)

Supongo que con eso se solucionara

salu2

JrcsDev

  • Miembro MUY activo
  • ***
  • Mensajes: 245
  • Nacionalidad: ve
    • Ver Perfil
    • http://codigo7.wordpress.com/
Re: Leer Archivos Binarios
« Respuesta #2 en: Jueves 29 de Junio de 2006, 18:29 »
0
Gracias amigo... no me habia fijado en eso.... pero mira, tengo otro problema... No sé como leer el archivo, es decir, creo que la condición que estoy colocando en el While no es la correcta... tampodo estoy seguro de la forma en que leo... revísalo a ver.. .y una vez más GRACIAS :)

Código: Text
  1. f=fopen(nomar,"wb");
  2.     while (fread(&p1, sizeof(persona), 1, f))
  3.     {  printf("\n%s",p1.nombre);
  4.     }
  5.     fclose(f);
  6.  

 :D
Sígueme en Twitter]
Donar comida a los chicos necesitados!
Todo lo puedo en Cristo que me fortalece...

Diodo

  • Moderador
  • ******
  • Mensajes: 658
    • Ver Perfil
    • http://www.solocodigo.com
Re: Leer Archivos Binarios
« Respuesta #3 en: Jueves 29 de Junio de 2006, 19:25 »
0
El bucle tiene buena pinta. fread devuelve el numero de registros leidos cada vez, por tanto si en el argumento tercero de la funcion que especifica el numero de registros a leer cada pasada de fread le pones 1, la funcion fread devolvera 1 siempre que lea un registro y por tanto se cumplira la condicion de bucle  y -1 o 0 cuando llegue al final del texto y saldra del bucle

De todas maneras estas usando un archivo txt, y lo que se suele usar en estos casos es un archivo .dat, no se si esto puede dar algun problema, o vale igualmente

Sobre este tema hay mucha informacion en internet asi que ya sabes:

esta pagina esta bien

http://www.conclase.net/c/ficheros/index.php?cap=002

Geo

  • Miembro de PLATA
  • *****
  • Mensajes: 1011
  • Nacionalidad: mx
    • Ver Perfil
    • http://hsblog.mexchip.com
Re: Leer Archivos Binarios
« Respuesta #4 en: Jueves 29 de Junio de 2006, 23:34 »
0
Cita de: "Diodo"
De todas maneras estas usando un archivo txt, y lo que se suele usar en estos casos es un archivo .dat, no se si esto puede dar algun problema, o vale igualmente
Se puede usar cualquier extensión para el archivo. El único detalle es que, Windows determina el tipo de archivos por su extensión, por lo que seguramente asociará tu .txt con algún editor de texto (el bloc de notas por ejemplo). Pero eso no tiene que ver nada con tu programa.

Para crear el archivo no necesitas las dos opciones de apertura que usas en tu código, con usar "ab" basta.
Para leer el archivo, tu ciclo while debe funcionar, pero estás abriendo el archivo con la opción incorrecta, debiera ser "rb" y no "wb".

Saludos,
JJ (Geo).
La imaginación es el límite.
Hardware & Software | Mexchip

JrcsDev

  • Miembro MUY activo
  • ***
  • Mensajes: 245
  • Nacionalidad: ve
    • Ver Perfil
    • http://codigo7.wordpress.com/
Re: Leer Archivos Binarios
« Respuesta #5 en: Viernes 30 de Junio de 2006, 19:52 »
0
Gracias!!! ese era el problema... ahora surge otro, y uno que nunca lo he podido solucionar. En la estructura de mi programa yo tengo un campo para nombre, uno para apellido y uno para la edad, todos ellos son arrays de char.

Código: Text
  1. typedef struct persona
  2. {    char nombre[10], apellido[10], edad[3];
  3. };
  4.  

Tengo problemas para realizar la lectura de los arreglos de char... Si utilizo el scanf("%s"), solo me toma la primera palabra de la cadena. Opté por usar gets, pero cuando ejecuto el programa me funciona bien la primera vez, y cuando vuelvo a ingresar a otra persona, el programa me salta la lectura del nombre y pasa a leer el apellido de una vez... Espero que alguien pueda ayudarme... Gracias! :)
Sígueme en Twitter]
Donar comida a los chicos necesitados!
Todo lo puedo en Cristo que me fortalece...

Geo

  • Miembro de PLATA
  • *****
  • Mensajes: 1011
  • Nacionalidad: mx
    • Ver Perfil
    • http://hsblog.mexchip.com
Re: Leer Archivos Binarios
« Respuesta #6 en: Sábado 1 de Julio de 2006, 02:37 »
0
Coloca el código y comenta el error que te presenta, porque la función gets() debería servirte para lo que quieres.

Saludos,
JJ (Geo).
La imaginación es el límite.
Hardware & Software | Mexchip

TRod

  • Miembro MUY activo
  • ***
  • Mensajes: 108
  • Nacionalidad: mx
    • Ver Perfil
Re: Leer Archivos Binarios
« Respuesta #7 en: Sábado 1 de Julio de 2006, 04:46 »
0
Hola. :hola:
Al parecer te has topado con el mismo problema que tuve hace tiempo con Turbo C. Nunca supe el porqué de los errores en los archivos binarios después de usar un scanf(...%s).
  La forma en que lo resolví fue deshaciendome completamente de scanf() e inventarme una función para leer cadenas de caracteres desde el teclado utilizando la función getch() (o sea, sin eco), y se acabaron mis problemas... de hecho jamas volvi a usar scanf() despues de eso.

Obviamente me hice lios con coordenas de pantalla, borrado de caracteres, limites del char[?],  el caracter '\0', etc. etc. etc... Pero creeme, valio la pena para todos los programas que hice bajo Turbo C que manejaban archivos binarios y aquella "vieja amiga BGI" :whistling: .

 Podría existir una mejor solución, pero la mia fue esa. Espero que la tomes en cuenta y te ayude.
Saludos.

JrcsDev

  • Miembro MUY activo
  • ***
  • Mensajes: 245
  • Nacionalidad: ve
    • Ver Perfil
    • http://codigo7.wordpress.com/
Re: Leer Archivos Binarios
« Respuesta #8 en: Sábado 1 de Julio de 2006, 07:37 »
0
Citar
Al parecer te has topado con el mismo problema que tuve hace tiempo con Turbo C. Nunca supe el porqué de los errores en los archivos binarios después de usar un scanf(...%s).
La forma en que lo resolví fue deshaciendome completamente de scanf() e inventarme una función para leer cadenas de caracteres desde el teclado utilizando la función getch() (o sea, sin eco), y se acabaron mis problemas... de hecho jamas volvi a usar scanf() despues de eso.

Con respecto a esto, en Pascal logré desarrollar una función que hacía todo lo que dices, y más nunca usé read o readln, pero bueno, aquí en C aún no me es necesario porque solo estoy aprendiendo archivos.... En futuro haré mi propia función... jejej, ahora, vamos con lo que requiero de momento...

Este es el programa completo:

Código: Text
  1. #include<conio.h>
  2. #include<stdio.h>
  3. #include<string.h>
  4. #define nomar "esperanza.dat"
  5. typedef struct persona
  6. {  char nombre[10],apellido[10],edad[3];
  7. };
  8.  
  9. void imprimir();
  10. void agregar();
  11. void menu();
  12.  
  13. FILE *f;
  14. persona p,p1;
  15. char k;
  16. int nr;
  17. char nom[10],ape[10],ed[3];
  18. void main()
  19. {   while (k!='3')
  20.   {  menu();
  21.     if (k=='1')
  22.       agregar();
  23.     if (k=='2')
  24.     imprimir();
  25.   }
  26. }
  27. void agregar()
  28. {   int i;
  29.   for (i=0;i<10;i++)
  30.   {  nom[i]=0;
  31.     ape[i]=0;
  32.   }
  33.   clrscr();
  34.   gotoxy(2,2);printf("Nombre: ");
  35.   //scanf("%10s", &nom);
  36.   gets(nom);
  37.   gotoxy(2,4);printf("Apellido: ");
  38.   //scanf("%10s", &ape);
  39.   gets(ape);
  40.   gotoxy(2,6);printf("Edad: ");
  41.   scanf("%3s", &ed);
  42.   if ((f=fopen(nomar,"rb"))==NULL)
  43.   {  f=fopen(nomar,"wb");
  44.   }
  45.   else
  46.   {  f=fopen(nomar,"a+b");
  47.   }
  48.   strcpy(p.nombre,nom);
  49.   strcpy(p.apellido,ape);
  50.   strcpy(p.edad,ed);
  51.  
  52.   fwrite(&p, sizeof(p), 1, f);
  53.   fclose(f);
  54. }
  55. void imprimir()
  56. {   clrscr();
  57.   f=fopen(nomar,"rb");
  58.   while (fread(&p1, sizeof(p1), 1, f)!=NULL)
  59.   {  printf("\n%20s %20s %20s",p1.nombre,p1.apellido,p1.edad);
  60.  
  61.   }
  62.   fclose(f);
  63.   getch();
  64.  
  65. }
  66. void menu()
  67. {  clrscr();
  68.   gotoxy(2,2);printf("MENU PRINICPAL");
  69.   gotoxy(4,4);printf("[1] - AGREGAR");
  70.   gotoxy(4,5);printf("[2] - IMPRIMIR");
  71.   gotoxy(4,6);printf("[3] - SALIR");
  72.   gotoxy(2,8);printf("Elija: ");
  73.   k='0';
  74.   while (!(k>='1' && k<='3'))
  75.   {  k=getch();
  76.   }
  77. }
  78.  

Ahora, el problema lo tengo en la función agregar.... Es probable que sea por no inicializar los arreglos... Lo cual nunca he entendido bien en C.

Esta es la función agregar, que simplemente agrega un nuevo registro a el fichero de estructura:

Código: Text
  1. void agregar()
  2. {   int i;
  3.   for (i=0;i<10;i++)
  4.   {  nom[i]=0;
  5.     ape[i]=0;
  6.   }
  7.   clrscr();
  8.   gotoxy(2,2);printf("Nombre: ");
  9.   //scanf("%10s", &nom);
  10.   gets(nom);
  11.   gotoxy(2,4);printf("Apellido: ");
  12.   //scanf("%10s", &ape);
  13.   gets(ape);
  14.   gotoxy(2,6);printf("Edad: ");
  15.   scanf("%3s", &ed);
  16.   if ((f=fopen(nomar,"rb"))==NULL)
  17.   {  f=fopen(nomar,"wb");
  18.   }
  19.   else
  20.   {  f=fopen(nomar,"a+b");
  21.   }
  22.   strcpy(p.nombre,nom);
  23.   strcpy(p.apellido,ape);
  24.   strcpy(p.edad,ed);
  25.  
  26.   fwrite(&p, sizeof(p), 1, f);
  27.   fclose(f);
  28. }
  29.  
  30.  

Cuando hago la lectura de los datos por primera vez, funciona perfecto, pero cuando vuelvo a llamar a la función agregar, entonces me salta el nombre y cae en la parte donde lee el apellido. Fíjense que aquí tengo con comentarios las instrucciones que usé al principio:

Código: Text
  1.   gotoxy(2,2);printf("Nombre: ");
  2.   //scanf("%10s", &nom);
  3.   gets(nom);
  4.   gotoxy(2,4);printf("Apellido: ");
  5.   //scanf("%10s", &ape);
  6.   gets(ape);
  7.   gotoxy(2,6);printf("Edad: ");
  8.   scanf("%3s", &ed);
  9.  
  10.  

Probé de las dos formas, y el resultado es el mismo... Espero por su ayuda amigos... Saludos!  :) y Gracias ;)
Sígueme en Twitter]
Donar comida a los chicos necesitados!
Todo lo puedo en Cristo que me fortalece...

Diodo

  • Moderador
  • ******
  • Mensajes: 658
    • Ver Perfil
    • http://www.solocodigo.com
Re: Leer Archivos Binarios
« Respuesta #9 en: Sábado 1 de Julio de 2006, 10:07 »
0
Esto me huele a fflush  :D

Es posible que el primer scanf se salte por que se ha quedado algo en el buffer de entrada. Prueba a poner fflush(stdin) despues del ultimo scanf (el scanf de la edad)

Código: Text
  1. fflush(stdin);
  2.  

salu2

JrcsDev

  • Miembro MUY activo
  • ***
  • Mensajes: 245
  • Nacionalidad: ve
    • Ver Perfil
    • http://codigo7.wordpress.com/
Re: Leer Archivos Binarios
« Respuesta #10 en: Sábado 1 de Julio de 2006, 10:45 »
0
Gracias Diodo, esa era la solución... jeje :)... Ahora tengo otra pregunta... Cómo hago para eliminar algun registro de ese archivo de estructura???... :)...
Sígueme en Twitter]
Donar comida a los chicos necesitados!
Todo lo puedo en Cristo que me fortalece...

Diodo

  • Moderador
  • ******
  • Mensajes: 658
    • Ver Perfil
    • http://www.solocodigo.com
Re: Leer Archivos Binarios
« Respuesta #11 en: Sábado 1 de Julio de 2006, 11:41 »
0
Supongo que habra varias maneras de hacerlo ...

Yo lo haria de esta forma:

- Una vez introducido el registro a borrar, vas leyendo mediante fread y preguntando si el fichero leido es el que quieres borrar

- Cuando lo encuentres , guardas la posicion del puntero al archivo en una variable (mediante la funcion ftell)

- Mediante la funcion fseek mueves el puntero 1 registro adelante y despues lees los registros desde ese punto hasta el final, guardandolos en unas estructuras auxiliares

- Finalmente haces otro fseek desde el inicio del archivo hasta la posicion que guardaste con el ftell, y sobreescribes los registros que guardaste en el paso anterior.Al final te quedara un registro repetido (el ultimo),supongo que se podra borrar escribiendo una estructura vacia sobre el ( no estoy seguro)

JrcsDev

  • Miembro MUY activo
  • ***
  • Mensajes: 245
  • Nacionalidad: ve
    • Ver Perfil
    • http://codigo7.wordpress.com/
Re: Leer Archivos Binarios
« Respuesta #12 en: Lunes 3 de Julio de 2006, 00:02 »
0
Cita de: "Diodo"
Supongo que habra varias maneras de hacerlo ...

Yo lo haria de esta forma:

- Una vez introducido el registro a borrar, vas leyendo mediante fread y preguntando si el fichero leido es el que quieres borrar

- Cuando lo encuentres , guardas la posicion del puntero al archivo en una variable (mediante la funcion ftell)

- Mediante la funcion fseek mueves el puntero 1 registro adelante y despues lees los registros desde ese punto hasta el final, guardandolos en unas estructuras auxiliares

- Finalmente haces otro fseek desde el inicio del archivo hasta la posicion que guardaste con el ftell, y sobreescribes los registros que guardaste en el paso anterior.Al final te quedara un registro repetido (el ultimo),supongo que se podra borrar escribiendo una estructura vacia sobre el ( no estoy seguro)
Gracias Diodo, parece un buen método, aunque aún no entiendo bien lo del fseek... Sabes? se me ocurre que podría usar dos archivos y hacer lo siguiente:

- Abro el archivo que tiene los registros
- Creo un archivo auxiliar del mismo tipo de estructura
- Recorro todos los registros en el primer archivo, y los voy copiando al auxiliar, TODOS, a excepción del registro que quiero eliminar.
- Luego paso todos los archivos del fichero auxiliar a el fichero donde guardo los datos...

Qué dicen? pudiera ser una buena opción??? o hay alguna otra manera más eficiente?  :whistling:
Sígueme en Twitter]
Donar comida a los chicos necesitados!
Todo lo puedo en Cristo que me fortalece...

Geo

  • Miembro de PLATA
  • *****
  • Mensajes: 1011
  • Nacionalidad: mx
    • Ver Perfil
    • http://hsblog.mexchip.com
Re: Leer Archivos Binarios
« Respuesta #13 en: Lunes 3 de Julio de 2006, 02:24 »
0
Otra sería cargar en memoria todos los registros, recorrerlos, al encontrar el que vas a borrar, copiar todos los registros siguientes a la posición anterior, finalmente eliminar la memoria ocupada por la última posición.

Saludos,
JJ (Geo).
La imaginación es el límite.
Hardware & Software | Mexchip