PDA

Ver la versión completa : recuperar una matriz en un fichero binario



robloz
31/08/2007, 17:53
Hola, con un primer programa guardo un archivo binario que posee esta estructura:
num_graf ancho alto y una matriz, el problema reside a al hora de recuperar la matriz
que en algunas posicones como en la [87,0] me empieza a poner valores distintos
a la matriz guardada (lo más seguro esk sean valores basura) y no se a que se puede
deber ya que compruebo la matriz antes de guardarla que sea correcta, aquí les dejo el
código por si alguien sabe que puede ser.
Muchas gracias
// creo el contenido del mapa
/* __________________________________________________ _________________________*/
// guardo el mapa
short int num_graf;
int ancho, alto;
short int **mapa;
string fichero;
ofstream of;
// .......................... (comandos)
of.open(fichero.c_str());
of.write(reinterpret_cast<char*>(&num_graf), sizeof(short int));
of.write(reinterpret_cast<char*>(&ancho), sizeof(int));
of.write(reinterpret_cast<char*>(&alto), sizeof(int));

for(int x=0; x<alto; x++)
of.write(reinterpret_cast<char*>(mapa[x]) , sizeof(short int)*ancho);
/* __________________________________________________ _________________________*/
// recuperar mapa
void Escenario::Inicializar(char* file_mapa, char* file_tipo){
ifstream fi, fi_tipo;

fi.open(file_mapa);
fi_tipo.open(file_tipo);
// comprobar si hay errores
if(fi.fail() || fi_tipo.fail())
cout<<"error al abrir el fichero "<<cerr<<endl;
fi.read(reinterpret_cast<char*>(&num_graf), sizeof(short int));
fi.read(reinterpret_cast<char*>(&ancho), sizeof(int));
fi.read(reinterpret_cast<char*>(&alto), sizeof(int));

// reservo memoria matriz del mapa
mapa = new short int*[alto];
for(int i=0; i<alto; i++)
mapa[i] = new short int[ancho];
// reservo memoria para la matriz de las colisiones
tipo = new int*[num_graf];
for(int i=0; i<num_graf; i++)
tipo[i] = new int[4];

for(int i=0; i<alto; i++)
fi.read( reinterpret_cast<char*>(mapa[i]) , sizeof(short int)*ancho);

for(int i=0; i<num_graf; i++)
fi_tipo.read(reinterpret_cast<char*>(tipo[i]) , sizeof(int)*4);

fi.close();
fi_tipo.close();

// cargo los gráficos
Cargar_Fondo2(grafico, num_graf);
};
/* __________________________________________________ _________________________*/

swapd0
31/08/2007, 18:40
Haz una prueba con un mapa de 2x2, asi te sera mas facil buscar los fallos.

DarkDijkstra
31/08/2007, 22:30
Se que es una pregunta tonta y obvia, pero m&#225;s de una vez me ha pasado por despistado... &#191;cierras correctamente los ficheros y tal al escribir, verdad?
incluso prueba a hacer un fi.flush() entre cada iteraci&#243;n del bucle de escritura para forzarla...
aunque lo mejor es, para ver si el problema est&#225; en la escritura o en la lectura, prueba a escribir una matriz que sean todo 49's (por ejemplo, para que luego veas 1's) y la abres con un editor de textos o algo y mira que pinta tiene, si en alg&#250;n momento ves que cambian los n&#250;meros es que algo falla al escribir...

swapd0
31/08/2007, 22:47
Si estas grabando datos en binario, lo mejor es usar un editor de ficheros, esos que ves a la izquierda los valores en hexadecimal y a la derecha el caracter que le corresponde.

Sobre el flush(), con hacerlo antes de cerrar el fichero es suficiente.

DarkDijktra, me encanta tu firma, real como la vida misma. :D

DarkDijkstra
31/08/2007, 22:54
Tienes razon en las tres cosas... lo del editor hexadecimal de ficheros es mas "profesional", aunque para ver simplemente si el fichero sale "raro" te vale cualquier editor. Lo del flush, haciendo un fi.close() incluso ni har&#237;a falta... es una man&#237;a que tengo yo desde que hice una clase para ir guardando un log de la apliaci&#243;n y hasta que no hice que "flusheara" despues de cada nueva l&#237;nea me dio algun problema.
Y si, yo creo que es lo mejor que he visto de dilbert... la vi en el trabajo, levant&#233; la vista, vi a mi jefe al fondo y no pude contenerme la risa XD

Reycat
01/09/2007, 00:08
Tienes razon en las tres cosas... lo del editor hexadecimal de ficheros es mas "profesional", aunque para ver simplemente si el fichero sale "raro" te vale cualquier editor. Lo del flush, haciendo un fi.close() incluso ni haría falta... es una manía que tengo yo desde que hice una clase para ir guardando un log de la apliación y hasta que no hice que "flusheara" despues de cada nueva línea me dio algun problema.
Y si, yo creo que es lo mejor que he visto de dilbert... la vi en el trabajo, levanté la vista, vi a mi jefe al fondo y no pude contenerme la risa XD



Je, je, a mí me pasó eso con esta otra:
http://img396.imageshack.us/img396/4027/dilbertmalvame4.th.gif (http://img396.imageshack.us/my.php?image=dilbertmalvame4.gif)

robloz
01/09/2007, 01:11
me he descargado el editor binario HHD software free hex editor y por lo k veo no hay nada raro, puede ser que haya que meterle alguna opci&#243;n a la hora de abrir el fichero .open(<file>, rb) o algo as&#237;?????

he probado con una matriz de 3x2 pero no me ha hecho nada raro, alguna ideilla m&#225;s????

< - >
me he dado cuenta que cada vez toman valores distintos, y es a partir de la fila 87 (tiene 100 filas) debe de haber alguna zona que no llegue a recorrer

< - >
en la lectura del fichero he a&#241;adido:
/*_________________________________________________ __*/
for(int i=0; i<alto; i++){
fi.read( reinterpret_cast<char*>(mapa[i]) , sizeof(short int)*ancho);
if(fi.gcount()!=sizeof(short int)*ancho)
cout<<"Error en la lectura del escenario fila: "<<i<<endl;
}
/*_________________________________________________ __*/
y resulta que las &#250;ltimas filas de la matriz no me lee los byte correspondientes
hay alguna forma de saber porque da este error??? algo estilo SDL_GetError(), ahhhh y una funci&#243;n que haga lo mismo que 'gcount' pero con un flujo de salida, para saber cuantos byte he escrito en el fichero


Gracias

DarkDijkstra
01/09/2007, 12:47
Que yo recuerde no tienes un gcount en los ofstreams, pero puedes intentar algo con tellp, que te devuelve un long con la posicion actual del "cursor" de escritura tras la ultima operaci&#243;n.
Asi, en cada iteraci&#243;n, sumale a una variable el tama&#241;o que hayas escrito y comp&#225;ralo con lo que te devuelva tellp.
Otra opci&#243;n es simplemente mirar el tama&#241;o del fichero resultante, eso si, si estas en windows, al darle a propiedades a un fichero mira el "Tama&#241;o", no el "Tama&#241;o en disco" para verlo.
Lo del editor de texto lo decia simplemente porque si creas una matriz que tenga el mismo valor en todas partes, luego la escribes a disco y abres ese fichero con un editor de texto normal, deberias ver un monton de caracteres iguales (menos al principio, claro, que guardas las tres variables). Si en algun punto ves que cambia, es que se ha escrito mal.
Tambien prueba a, al leer de disco, inicializar la matriz a cero por ejemplo (un valor diferente a lo que hayas puesto en la matriz a la hora de guardarla). Si ves que tras cargar, en algunas partes de la matriz hay valores cero, el problema es al cargar, si hay otro valor (diferente al que pusiste en la matriz a la hora de escribir en disco) el problema esta al grabar.

robloz
01/09/2007, 21:28
Hola, he a&#241;adido a la escritura del archivo esto:
/*_______________________________________________*/
for(int x=0; x<alto; x++){
of.write(reinterpret_cast<char*>(mapa[x]), sizeof(short int)*ancho);
byte_leidos += sizeof(short int)*ancho;
if(byte_leidos!=of.tellp()){
perror("Error escribir");
cout<<"fila del escenario: "<<x<<endl;
byte_leidos = of.tellp(); // para igualarlo y comprobar los siguientes
}
}
/*_______________________________________________*/

y el resultado que obtengo es que en los valores que me falla la lectura me falla en la escritura ( se escriben menos byte de los que deber&#237;a escribir) el caso es que el mensaje de 'perror("Error escribir");' me dice que 'no error' he estado comprobando que la matriz a escribir est&#233; bien, no se que puede fallar, he probado este programa con .net y no me sale ning&#250;n tipo de error, pero como sizeof(short int) cambia de un compilador a otro el fichero generado no me sirve.
&#191; qu&#233; me puede estar pasando?

DarkDijkstra
01/09/2007, 21:42
Todo empieza a apuntar a un rayo c&#243;smico o expediente X similar... XD
creo que lo que toca es "debuggear" el c&#243;digo, parar la ejecuci&#243;n en el momento en que comience a escribir mal (o deje de escribir, vamos) e intentar ver que est&#225; pasando... ahora mismo no se me ocurre que puede ser.

Si quieres p&#225;same el c&#243;digo y lo pruebo en linux (asumiendo que lo est&#225;s probando en visual studio o similar) y te comento (prometo no robarte el codigo ; )

swapd0
01/09/2007, 22:21
Que no se te olvide de abrir el fichero usando "wb" y "rb" (con la fstream no me acuerdo si se usan otros valores)para decir que es en binario, o puedes tener problemas.
Por ejemplo, en modo texto en cuanto se encuentre con un '\0' (byte 0), lo interpretara como final del fichero, ademas un '\n' (byte 0xa)te escribira 2 bytes...

kounch
03/09/2007, 23:58
¿Por qué no pruebas a escribirlo al revés? Es decir, invirtiendo los bucles.

Si al hacerlo así te sigue poniendo mal los mismos valores de las mismas coordenadas de la matriz, entonces es un problema de corrupción de memoria o desbordamiento. Si no, a lo mejor encuentras otras pistas.

robloz
05/09/2007, 13:56
ya he conseguido arreglarlo, se ve que es por que a la hora de abrir el fichero no he especificado nada y ten&#237;a que poner rb,

MUCHAS GRACIAS A TODOS

XD

DarkDijkstra
05/09/2007, 16:47
y el ganador... swapd0! XD