[ Foro de C ]
Saludos al foro, tengo un problema al ejecutar el presente codigo. El programa Graba una matriz de enteros en un archivo y despues lo lee del mismo archivo y lo muestra en pantalla, la grabación es OK, pero la lectura con fread() solo me muestra la mitad de los elementos de la matriz.
ret = fread(&matriz, object_size, object_count, flujo);
fread me devuelve el numero de objetos grabados (lo recupero en ret); Este valor debe a su vez debe coincidir con object_count.
matriz grabada matriz leida
2 4 6 8 10 2 4 6 8 10
12 14 16 18 20 12 14 16 18 20
22 24 26 28 30 22 24 0 0 0
32 34 36 38 40 0 0 0 0 0
42 44 46 48 50 0 0 0 0 0
Detalles Sistema
SO: Windows XP, Compilador: gcc 4.5.2 (MinGW)
int main(){
int fila, col, lfallo;
FILE *flujo;
int close_error;
char archivo[]="numbers.dat";
size_t object_size = sizeof(int);
size_t object_count = 25;
size_t ret;
int matriz[5][5]={2,4,6,8,10,
12,14,16,18,20,
22,24,26,28,30,
32,34,36,38,40,
42,44,46,48,50
};
printf("Valores iniciales de la matriz\n");
for(fila=0; fila <=4; fila++){
for(col=0;col<=4; col++)
printf("%d ",matriz[fila][col]);
printf("\n");
}
flujo = fopen(archivo, "w");
ret = fwrite(&matriz, object_size, object_count, flujo);
if (ret != object_count)
printf("Error al excribir datos al archivo\n");
else
printf("Datos escritos al archivo satisfactoriamente\n");
fflush(flujo);
close_error = fclose(flujo);
if (close_error!=0)
printf("No se puedo cerrar el archivo '%s'\n", archivo);
else
printf("archivo '%s' cerrado\n", archivo);
printf("===========================================\n");
/*VACIAMOS EL ARCHIVO*/
printf("Zeroing matriz...\n");
for (fila = 0; fila <= 4; fila++){
for(col=0; col <= 4; col++){
matriz[fila][col]=0;
printf("%d ", matriz[fila][col]);
}
printf("\n");
}
printf("===========================================\n");
/*LEEMOS EL ARCHIVO*/
printf("Ahora leeremos datos almacenados del archivo..!\n\n");
flujo = fopen(archivo, "r");
if (flujo==NULL)
printf("No se pudo abrir archivo '%s'\n", archivo);
else
printf("Archivo '%s' abierto ..!\n", archivo);
ret = fread(&matriz, object_size, object_count, flujo);
lfallo= (ret != object_count);
if (lfallo)
printf("Error leyendo data desde archivo...!\n");
else
printf("Leyendo datos del archivo satisfactoriamente\n");
for (fila =0; fila<=4 ; fila++){
for (col=0; col>=4; col++)
printf("%d ", matriz[fila][col]);
printf("\n");
}
fclose(flujo);
return 0;
}
Referencia. ejemplo tomado del libro "GNU C Programming Tutorial" (pag 114).
Es que estás mezclando dos formas distintas de acceder a fichero:
- Si quieres escribir con "fprintf", lo razonable es que leas con "fscanf".
- Si quieres leer con "fread", deberías escribir con "fwrite".
Escoge una de esas dos formas de trabajar, y aplícala en las dos partes del programa (cargar y guardar).
Me parece que te has confundido, si miras bien el codigo estoy usando fwrite() y fread() para escribir y leer una matriz.
No he usado fprintf en ningún lado, solo he usado printf para mostrar mensajes y los datos en la pantalla. como depuracion, no para escribir en el archivo.
De todas formas gracias por tu atención.
PROBLEMA SOLUCIONADO:
Resulta que bajo windows hay 2 modos de abrir los archivos, en modo binario y en modo texto.
En modo texto la secuencia 0A en este caso se traduce erroneamente como el fin de una linea, entonces al leer/escribir divide el contenido en lineas, y por eso trunca el contenido. De hecho, el tamaño de tu archivo era de 101 bytes y no 100 bytes (25x4) como debia ser, ya que convertia el 0A en 0D 0A al escribir. En windows cada linea lleva un retorno de carro / avance de linea, en linux solo existe el avance de linea 0A, y todos los archivos se manejan como si fueran binarios.
Si no especificas el modo, los archivos se abren por defecto en modo texto.
La solucion es especificar explicitamente que vamos a abrir el archivo en modo binario, de esa forma se elimina el problema.
Se debe cambiar las siguientes lineas:
Cambiar--> flujo = fopen(archivo, "w");
por ---> flujo = fopen(archivo, "wb");
y
Cambiar--> flujo = fopen(archivo, "r");
por ---> flujo = fopen(archivo, "rb");
No es un problema sencillo de resolver, pero es una solución muy importante a tener en cuenta.
:)
Efectivamente, ese es el problema. Hay tantos "printf" que en un primer vistazo me había parecido que volcabas los datos con printf, pero no es así, sino que el modo de apertura es incorrecto.
Pero lo que que haya dos modos de abrir archivos no es bajo Windows, sino en cualquier compilador de C.
Conceptualmente, si el fichero es binario (vas a leer con "fread" y escribir con "fwrite"), deberías abrirlo con "rb" o "wb", según el caso, pero no sólo porque trabajas en Windows, sino porque se supone que pretendes manejar un fichero binario. ;-)
Eso sí, es fácil que el problema se agrave con Windows, que convierte los avances de línea \n en dos caracteres, con lo que el fichero (si contiene caracteres de avance de línea) se descuadre.
Pero insisto: oblígate a usar "rt" o "rb" según el caso, en vez de "r" como modo de apertura (mira el apartado 6 del curso):
http://www.aprendeaprogramar.com/mod/forum/discuss.php?d=530
(No se puede continuar esta discusión porque tiene más de dos meses de antigüedad. Si tienes dudas parecidas, abre un nuevo hilo.)