Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Synth3tik0 en 31 Julio 2014, 04:32 am



Título: Como escribir puntero a objetos en el disco duro para posteriorment recuperarlo?
Publicado por: Synth3tik0 en 31 Julio 2014, 04:32 am
miclase *mipuntero = new miclase[20];

Tendría  20 objetos  de tipo miclase.. Como los guardo en un archivo y como los cargo de nuevo?

Podrían colocar un ejemplo(De prefencia en estilo C++)?


Título: Re: Como escribir puntero a objetos en el disco duro para posteriorment recuperarlo?
Publicado por: eferion en 31 Julio 2014, 08:43 am
Dado que los objetos de C++ son bastante propensos a utilizar memoria dinámica: punteros internos, contenedores de la stl, ... no suele ser buena idea hacer una copia "a lo bestia" del contenido de la memoria, ya que así pierdes la información almacenada mediante punteros.

La mejor forma de guardar objetos ( para almacenarlos en disco, enviarlos por red, etc. ) es hacer el trabajo "a mano", es decir, extraer toda la información que permite reconstruir el objeto y almacenar dicha información:

Código
  1. class POO
  2. {
  3.  public:
  4.  
  5.    int Numero( ) const
  6.    { return numero; }
  7.  
  8.    std::string Nombre( ) const
  9.    { return nombre; }
  10.  
  11.    const std::vector< float >& Valores( ) const
  12.    { return valores; }
  13.  
  14.  private:
  15.    int numero;
  16.    std::string nombre;
  17.    std::vector< float > valores;
  18. }
  19.  
  20. void Serializar( POO* poo, Stream* stream )
  21. {
  22.  stream.write( poo->Numero( ) );
  23.  stream.write( poo->Nombre( ) );
  24.  
  25.  stream.write( poo->Valores( ).size( ) ); // Numero de elementos del array
  26.  for ( const auto& valor : poo->Valores( ) )
  27.    stream.write( valor );
  28. }
  29.  
  30. POO* Deserializar( Stream* stream )
  31. {
  32.  POO* poo = new POO( );
  33.  poo->SetNumero( stream->readNumber( ) );
  34.  poo->SetNombre( stream->readString( ) );
  35.  
  36.  int numValores = stream->readNumber( );
  37.  std::vector< float > valores;
  38.  for ( int i = 0; i < numValores; i++ )
  39.    valores.push_back( stream->readFloat( ) );
  40.  poo->SetValores( valores );
  41.  
  42.  return poo;
  43. }

El ejemplo es ambigüo ya que la forma concreta de "serializar" el objeto depende en gran medida del formato en el que se va a almacenar: archivo binario, XML, base de datos, ...

Faltan algunos métodos en "POO"... pero no deberían suponer ningún problema para entender el código.


Título: Re: Como escribir puntero a objetos en el disco duro para posteriorment recuperarlo?
Publicado por: Synth3tik0 en 1 Agosto 2014, 05:40 am
Entonces los métodos no se pueden guardar?



readFloat( ) como  funciona? como avanzas en el stream(suponiendo que es un archivo binario) hacia adelante?


Título: Re: Como escribir puntero a objetos en el disco duro para posteriorment recuperarlo?
Publicado por: eferion en 1 Agosto 2014, 08:21 am
readFloat( ) como  funciona? como avanzas en el stream(suponiendo que es un archivo binario) hacia adelante?

stream lo he puesto a modo de ejemplo. Cuando "serializas" un objeto, es decir, cuando extraes de el su estado para poder reconstruir el objeto en el futuro, forzosamente tienes que guardar esta información en algún sitio: un fichero, enviarlo por red, ... curiosamente todas estas opciones funcionan mediante streams.

Si vas a almacenar la información en disco entonces podrías usar "ofstream" para guardar y "ifstream" para leer... como ves no dejan de ser streams. Los métodos concretos que te permitan manejar cada una de estas clases los tienes en internet, buscando un poco se encuentran.

En cuanto al 'readFloat' no es más que un hipotético método que me permite obtener un float del stream... simplemente. Dependiendo de la interfaz del stream, este método puede llamarse así, o simplemente 'read' o vete tu a saber como... depende de la interfaz del stream.

Y tratando el tema de "avanzar en el stream", se supone que cada vez que tu haces una lectura de un stream el puntero de lectura que tiene interno avanza solo, por lo que, por norma general, no debes preocuparte de este aspecto.