Autor
|
Tema: Acceso aleatorio a archivos binarios, a ver si alguien puede ayudarme (Leído 8,763 veces)
|
Awraaaauu
Desconectado
Mensajes: 6
|
Si alguien ve que lo que digo es una tontería que me corrija y pase de leer el código. Mi intención aquí era escribir y leer de un archivo binario usando streams. De manera que Datos -> Estructura(a lo buffer) -> archivo.dat y viceversa. Para saber dónde y desde dónde leer he usado seekg y seekp, multiplicando el número de registro por sizeof(estructura). El problema es que cuando introduzco un segundo registro me sobrescribe el primero con NULL las veces que sea necesario hasta llenar el hueco. Ahí va el código: #include <iostream> #include <cstring> #include <cstdio> #include <fstream> using namespace std; //Estrucutra / Buffer typedef struct { char nombre[34]; int ano; short dia; short mes; } Cumple; //Prototipos void introduccion(); char ElegirConsulta(); void ConsultaID(); void grabado(); void lectura(); //Variables Globales char meses[12][11] = {"Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"}; long nRegistros = 0; long nBytes = 0; int id; Cumple pers; //Función Principal int main() { int opt; bool bucle = false; while(!bucle) { system("cls"); ifstream fichero("datos.dat", ios::in | ios::binary); fichero.seekg(0, ios::end); // Colocar el cursor al final del fichero nBytes = fichero.tellg(); // Tamaño en bytes nRegistros = fichero.tellg()/sizeof(Cumple); // Tamaño en registros fichero.close(); cout << "Acci\242n:" << endl; cout << " 1 - Introducir datos" << endl; cout << " 2 - Consultar datos" << endl; cout << "99 - Salir" << endl; cout << "Opci\242n: "; cin >> opt; switch(opt) { case 1: introduccion(); break; case 2: if(ElegirConsulta() == 'a') ConsultaID(); break; case 99: cout << "Vete ya CO\245O!!!" << endl; cin.get(); cin.get(); bucle = true; } } return 0; } //Función de introducción de datos void introduccion() { bool correcto = false; char op; cin >> id; while(!correcto) { system("cls"); cout << "ID: " << id << endl; cout << "Nombre: "; cin >> pers.nombre; cout << endl; cout << "A\244o: "; cin >> pers.ano; cout << endl; cout << "Mes: "; cin >> pers.mes; cout << endl; cout << "D\241a: "; cin >> pers.dia; cout << endl; cout << endl << endl; cout << "Datos introducidos: " << endl; cout << pers.nombre << " naci\242 el " << pers.dia << " de " << meses[pers.mes-1] << " de " << pers.ano << endl; cout << "Es esto correcto?(S/n)" << endl; cin >> op; if(op == 'S' || op == 's') correcto = true; } grabado(); } //Menu de consulta char ElegirConsulta() { char op; system("cls"); cout << "C\242mo quieres consultar?" << endl; cout << "a) Por ID" << endl; cout << "b) Por nombre" << endl; //Por hacer cout << "x) Atr\240s" << endl; cout << "Opci\242n: "; cin >> op; return op; } //Función de Consulta de datos por ID void ConsultaID() { system("cls"); cout << "Escribe ID: "; cin >> id; lectura(); cout << pers.nombre << " naci\242 el " << pers.dia << " de " << meses[pers.mes-1] << " de " << pers.ano << endl; cin.get(); cin.get(); } //Función de grabado de datos en fichero binario void grabado() { fstream grabado; grabado.open("datos.dat", ios::out | ios::trunc | ios::binary); grabado.seekp(id*sizeof(Cumple), ios::beg); grabado.clear(); grabado.write((const char *)&pers, sizeof(Cumple)); grabado.close(); } //Función de lectura de datos de fichero binario void lectura() { fstream lectura; lectura.open("datos.dat", ios::in | ios::binary); lectura.seekg(id*sizeof(Cumple), ios::beg); lectura.read((char *)&pers, sizeof(Cumple)); lectura.close(); }
¿Alguien sabe qué hago mal? Por cierto, en WinXP, 32bits, con DevC++
|
|
« Última modificación: 23 Junio 2010, 06:35 am por Littlehorse »
|
En línea
|
|
|
|
Littlehorse
All the world's a stage
Moderador
Desconectado
Mensajes: 2.714
Nie Dam Sie
|
Bueno lo primero y principal es que deberías no utilizar tanto las variables globales. Hacen el código un poco mas difícil de seguir ya que cualquier función puede modificar su contenido. En cuanto al problema, el principal esta en la apertura del archivo. Tanto ios::out como ios::out|ios::trunc primero descartan el contenido (crean el archivo solo si no existe, pero descartan el contenido existente en el).
Otra cosa que veo que deberías modificar es el método del calculo de posiciones, es bastante propenso a errores. Supongamos que no tenes ningún dato, y el ID es 1400, tu archivo quedaría algo así:
1400*sizeof(data)bytes NULL|NULL|NULL|NULL|| contenido ||
lo cual no es lo mas adecuado y de seguro te traerá problemas como archivos excesivamente grandes, punteros a archivo que no apuntan donde deben, superposición de datos y demás.
No he visto mucho mas, pero también deberías chequear los estados del stream (failbit, badbit, etc) para asegurarte de evitar otros tipos de errores.
Como ultimo, las etiquetas GeSHI utilízalas de esta forma:
C [code=c]codigo[/code]
C++ [code=cpp]codigo[/code]
Saludos!
|
|
|
En línea
|
An expert is a man who has made all the mistakes which can be made, in a very narrow field.
|
|
|
Awraaaauu
Desconectado
Mensajes: 6
|
Muchas gracias por tú respuesta.
Se que el código es una "basurita", pero realmente la única función que tenía era conseguir aprender lo de los binarios, le adorné con lo del calendario para que luego no me quedara un exe inútil.
¿Hay alguna función para lo que busco o tengo que crear un buffer para TOODOO el archivo?
|
|
|
En línea
|
|
|
|
Littlehorse
All the world's a stage
Moderador
Desconectado
Mensajes: 2.714
Nie Dam Sie
|
No no hay ninguna. Si queres escribir los datos en forma aleatoria, basta con poner el puntero en una posición relacionada con algún criterio variante, lo cual es precisamente lo que estas haciendo ahora y teóricamente mal no esta (a pesar que tenga los problemas que ya mencione antes). El problema radica en que en cada apertura descartas el contenido del archivo existente.
Obviamente tenes mil formas de ordenar el archivo, lo ideal en este caso seria que cada estructura este detras de la otra en pos de no perder el acceso aleatorio y obtener un archivo lo mas reducido posible.
No veo la necesidad de crear un buffer para todo el archivo, no te daría ninguna ventaja respecto de lo que estas haciendo y en algún punto incluso te podría traer problemas cuando el tamaño del archivo sea considerablemente grande.
Saludos
|
|
|
En línea
|
An expert is a man who has made all the mistakes which can be made, in a very narrow field.
|
|
|
Awraaaauu
Desconectado
Mensajes: 6
|
Mi pregunta es:
¿Cómo evitar que lo descarte?
|
|
|
En línea
|
|
|
|
Littlehorse
All the world's a stage
Moderador
Desconectado
Mensajes: 2.714
Nie Dam Sie
|
Modificando la apertura del archivo para que no vacié el contenido, busca sobre los métodos de apertura. ::app por ejemplo te podría servir, pero primero tienes que modificar el método de calculo de posiciones.
Saludos
|
|
|
En línea
|
An expert is a man who has made all the mistakes which can be made, in a very narrow field.
|
|
|
Awraaaauu
Desconectado
Mensajes: 6
|
Muchas gracias, no conocía ese método. Aprendí de un manual bastante incompleto.
|
|
|
En línea
|
|
|
|
Littlehorse
All the world's a stage
Moderador
Desconectado
Mensajes: 2.714
Nie Dam Sie
|
De nada, para eso estamos . En cuanto a lo del manual, no se cual estarás leyendo pero tenes un post en las chinchetas con varios libros para elegir. Cualquier cosa ya sabes. Saludos!
|
|
|
En línea
|
An expert is a man who has made all the mistakes which can be made, in a very narrow field.
|
|
|
Awraaaauu
Desconectado
Mensajes: 6
|
Sigue habiendo un problemilla.
::app me sitúa al final del fichero siempre antes de cualquier operación de salida, incluso después de hacer seekp
Bueno, voy a investigar un poco por mi cuenta. Si no consigo nada lo haré sin streams.
|
|
|
En línea
|
|
|
|
nicolas_cof
Desconectado
Mensajes: 348
Into the Wild
|
Awraaaauu, prueba con ios::ate en vez de ios::app, ya que con ::app incluso si se cambia la posicion en el archivo siempre se escribe al final de este.
Salu10.
|
|
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
MediaFire impide el acceso a sus archivos desde Google en lo que puede ser la...
Noticias
|
wolfbcn
|
2
|
4,166
|
4 Febrero 2012, 15:59 pm
por farresito
|
|
|
¿Duda que archivos puede estar el spoiler de identi alguien me dice ?
Foro Libre
|
Weeken
|
0
|
1,763
|
28 Marzo 2013, 05:18 am
por Weeken
|
|
|
Leer archivos de acceso aleatorio con reinterpet_cast
« 1 2 »
Programación C/C++
|
patilanz
|
13
|
6,111
|
24 Marzo 2014, 23:13 pm
por patilanz
|
|
|
Duda Manejo De Archivos De Acceso Aleatorio
Programación C/C++
|
Omar_2013
|
2
|
2,482
|
1 Abril 2014, 20:22 pm
por Omar_2013
|
|
|
router acceso aleatorio
Hacking Wireless
|
onic
|
8
|
4,488
|
19 Agosto 2014, 15:21 pm
por simorg
|
|