Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros entornos y lenguajes > C++ Builder
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 08-12-2016
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
ofstream o rename fallan

Bueno la verdad es que no se me ocurria otro titulo. El caso es que estoy liado siguiendo aprendiendo cosas y estoy creando una mini clase la cual hace cosas basicas con archivos secuenciales pero el metodo Delete de mi clase me da problemas. Este es el codigo:
Código PHP:
int DatosPersonales::Delete(int id){
    
int retval = -1;
    
unsigned char *block;
    
long size_block_beg,size_block_end;
    
streampos pos;

    if(
filename != ""){
        
//Busco el ID a borrar del archivo
        
pos = (SearchFirst(id,NULL,false) * sizeof(DATOS)) - sizeof(DATOS);

        if(
pos >= 0){ //Si existe...
            //Abro el archivo para leer de el
            
ifstream f_infilename.c_str(), ios::binary );
            if(!
f_in.is_open()){
                
cout << "No se pudo crear el archivo " << filename << endl;
                return -
2;
            }
            
//Obtengo el tamaño de los bloques anterior y posterior al dato del id elegido
            
f_in.seekg0ios::end );
            
size_block_end f_in.tellg() - pos sizeof(DATOS);
            
f_in.seekg0ios::beg );
            
size_block_beg f_in.tellg() + pos;

            
//Creo un archivo auxiliar donde copiaré todo menos el dato del id elegido
            
ofstream f_out"aux.dat",ios::binary );
            if(!
f_out.is_open()){
                
cout << "No se pudo crear el archivo auxiliar." << endl;
                return -
2;
            }
            
//Si el tamaño del bloque anterior es mayor que 0 es porque hay datos antes y tengo
            //que meterlos en el archivo auxiliar
            
if(size_block_beg 0){
                
block = new unsigned char[size_block_beg];
                
f_in.read(block,size_block_beg);
                
f_out.write(block,size_block_beg);
                
delete[] block;
            }
            
//Si el tamaño del bloque posterior es mayor que 0 es porque hay datos despues y tengo
            //que meterlos en el archivo auxiliar
            
if(size_block_end 0){
                
f_in.seekgsizeof(DATOS), ios::cur );
                
block = new unsigned char[size_block_end];
                
f_in.read(block,size_block_end);
                
f_out.write(block,size_block_end);
                
delete[] block;
            }
            
//Cierro ambos archivos
            
f_in.close();
            
f_out.close();
            
//Elimino el archivo original y renombro el auxiliar al nombre del original
            
remove(string("_" filename).c_str());
            
rename(filename.c_str(), string("_" filename).c_str());
            
rename("aux.dat",filename.c_str());
            
retval=0;
        }
    }else{
        
retval=-3;
    }
    return 
retval;

No me da ningun aviso de que no se haya abierto bien f_out ni da ningun tipo de excepcion con el metodo read de este pero el archivo no aparece en el directorio del proyecto y a la hora de ejecutarse el rename ultimo, que es el que dejará este archivo con el nombre del original, no se renombra con lo que me quedo sin el archivo. No se que hago mal para que no aparezca el archivo aux.dat en el directorio del proyecto. Ya probé a poner la ruta completa pero tampoco funciona.
¿Pueden ayudarme?
Responder Con Cita
  #2  
Antiguo 09-12-2016
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola.

Desconozco el por que del cálculo de los bloques para borrar un registro de manera secuencial. Pero, básicamente un borrado de ese tipo consiste en crear un archivo temporal, para luego recorrer el archivo original e ir copiando al temporal los elementos diferentes al que debe ser borrado.
Por último se borra el archivo original y se renombra al archivo temporal como el original.

Básicamente sería algo similar a este ejemplo:
Código PHP:
#include <fstream>
...
struct DatosPersonales {
  ...
  
DatosPersonales();
  
void deleteID( const int id );
  ...
private:
  
struct {
    
int  id;
    
char nombre[20];
    
char apellidos[30];
    
int  edad;
  } 
Datos;

  
charFILE_NAME;
  
charFILE_TEMP;
  ...
};

DatosPersonales::DatosPersonales()
{
  
FILE_NAME "original.dat";
  
FILE_TEMP "temporal.dat";
  ...
}

void DatosPersonales::deleteID( const int id )
{
  
std::fstream fsInFILE_NAMEstd::fstream::in );
  
std::fstream fsOutFILE_TEMPstd::fstream::out );

  while ( ! 
fsIn.eof() ) {
    
fsIn.readreinterpret_cast<char*>( &Datos), sizeofDatos ) );
    if ( !
fsIn.eof() && Datos.id != id )
      
fsOut.writereinterpret_cast<char*>( &Datos), sizeofDatos ) );
  }

  
fsIn.close();
  
fsOut.close();

  
std::removeFILE_NAME );
  
std::renameFILE_TEMPFILE_NAME );
}
... 
Uso:
Código PHP:
...
{
   
DatosPersonales dp;
   ...
   
dp.deleteID);
   ... 
Claro está que borrar de modo secuencial una estructura solo se justifica en calidad de prueba, ya que es significativamente mas eficiente hacerlo de forma aleatoria.

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #3  
Antiguo 09-12-2016
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Lo de los bloques es para no tener que ir copiando estructura por estructura, o sea obtengo la posición del dato que quiero buscar y a partir de esa dirección obtengo el número de bytes que hay desde el inicio hasta esa posición y lo mismo para lo que hay después. Con eso hago solo dos write y me ahorro tener que recorrer todo el archivo leyendo y escribiendo dato a dato.
Lo que dices de "hacerlo de forma aleatoria" ¿que es eso?
Responder Con Cita
  #4  
Antiguo 09-12-2016
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola.

En este enlace tenes el tema bastante bién explicado: Archivos de acceso aleatorio

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #5  
Antiguo 09-12-2016
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Ya entendí aunque tiene algún que otro inconveniente ya que si quiero eliminar un id determinado y no están ordenados ya no sirve este método y si lo están pero no son todos correlativos también habría problemas. Para usarlo tendría que mostrar todos los registros y poner por ejemplo el contador de registros leídos delante de cada registro usando dicho contador para elegir el registro a borrar.
Sigo sin ver el porque no se crea el archivo auxiliar.
Responder Con Cita
  #6  
Antiguo 09-12-2016
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Cita:
Empezado por aguml Ver Mensaje
...
Sigo sin ver el porque no se crea el archivo auxiliar.
Lamentablemente no puedo probar tu código por que carezco de algunas funciones y datos para hacerlo, pero si revisas el código del mensaje #2, verás que hace sin problemas esa taréa.
Es decir:
  1. Crea el archivo auxiliar
  2. Pasa los registros que no se eliminarán
  3. Elimina el archivo original
  4. Renombra el archivo auxiliar como el original
Si te pudiera resultar útil avisame y te adjunto los fuentes de la prueba.

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #7  
Antiguo 10-12-2016
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Misterios de Windows. Cambié el nombre del archivo auxiliar de "aux.dat" a "temp.dat" y ya funciona. Sólo falla con el nombre de archivo "aux.dat". Eso me da que pensar que ha fallado algo en windows y al crear el archivo no permite hacerlo porque intente sobre escribirlo y al no existir pues... no se, son especulaciones. Luego cuando llegue intentare mover todo a otra carpeta y ver que pasa.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Conexiones que fallan con W7 64 y funcionan con WXP SP3 gorsan Conexión con bases de datos 4 11-03-2015 14:45:45
rename() y remove() fedee C++ Builder 2 31-05-2011 21:41:39
Problema con flujo OFSTREAM nax C++ Builder 4 23-09-2005 01:13:23


La franja horaria es GMT +2. Ahora son las 05:08:02.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi