Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 28-09-2006
Uoha Uoha is offline
Registrado
 
Registrado: sep 2006
Posts: 3
Poder: 0
Uoha Va por buen camino
Cargar/Guardar un objeto de una clase propia

Hace un par de meses que empecé con este bello lenguaje, y me estuve quemando las pestañas de diversas formas pero sin poder solucionar este problema. Por lo que entendí lo que estoy haciendo está bien, pero no lo convenzo al programa, que sigue sin hacer lo que yo quiero
Este es el código que tengo escrito
Código Delphi [-]
unit PruebaExport;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls, PruebaExport2;
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormActivate(Sender: TObject);
  private
  public
  end;
var
  Form1: TForm1;
  F:Finanzas;
  S : TFileStream;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
  f:=finanzas.Create(self);
  F.Integrantes := 10;
  F.Banda := 20;
  F.Coordinador :=30;
  F.Agente := 40;
  F.Porcentaje := true;
  S := tfilestream.Create('C:\archivo',fmCreate);
  s.Write(F,100);
  showmessage(f.todo);
  f.Free;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
S : TFileStream;
begin
  s := TFileStream.Create('C:\archivo',fmOpenRead);
  f := finanzas.Create(self);
  s.Read(F,100);
  s.Free;
end;
procedure TForm1.FormActivate(Sender: TObject);
begin
  showmessage(F.Todo);
end;
end.

Código Delphi [-]

unit PruebaExport2;
interface
uses
  SysUtils, Classes;
type
  TIO = class(TDataModule)
  private
  public
  end;
  
  Finanzas = class(Tcomponent)
  function Todo:string;
  public
    Integrantes,Banda,Coordinador,Agente : Single;
    Porcentaje : boolean;
  end;

var
  IO: TIO;

implementation
{$R *.dfm}

function Finanzas.Todo: string; // Muestra las variables.
begin
  if porcentaje = true then
  result := floattostr(integrantes) + '  ' + floattostr(coordinador)
        + '  ' + floattostr(banda) + '  ' + floattostr(agente) + ' Sí'
  else
  result := floattostr(integrantes) + '  ' + floattostr(coordinador)
        + '  ' + floattostr(banda) + '  ' + floattostr(agente) + ' No';
end;
end.

Para probarlo:
  1. Comento la parte que lee el archivo
  2. Compilo
  3. Clickeo el botón (se guarda la información, sale el messagebox)
  4. Cierro el programa
  5. Descomento lo que comenté
  6. Compilo
  7. Me sale el msgbox con todos valores '0'. Si saco 'F := finanzas.create;' en la parte de lectura, el message box inicial me da unos números rarísimos...
¿Qué estoy haciendo o escribiendo mal?
Muchas gracias
Responder Con Cita
  #2  
Antiguo 28-09-2006
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Poder: 27
jachguate Va por buen camino
La variable F, como tal es un puntero, un número de 4 bytes que indica una dirección en memoria. Cuando vos haces
Código Delphi [-]
s.Write(F,100);
En realidad estas escribiendo un número de 4 bytes (la dirección que tenía en memoria la instancia que creaste en esa corrida en particular).

Claro que cuando ejecutes otra vez el programa, aún cuando recuperés la dirección, en la memoria no habrá una instancia válida del objeto.

Lo que a vos te hace falta es que tu clase sea auto-persistente, en palabras mas modernas, que sea "serializable".

Esto podrías lograrlo dotando de un par de métodos a la clase, por decir: SaveToStream, LoadFromStream, que se encarguen de escribir y leer todas las propiedades de un stream.

Otra posibilidad, mas elaborada, es que crees una clase que sirva de ancestro a todas tu jerarquía, y que dicha clase tenga la lógica para escribir/leer las propiedades publicadas en un stream. Deben ser las propiedades publicadas porque es para estas para las que tenes información de tipo en tiempo de corrida (RTTI).

Finalmente, podrías derivar tus clases de TComponent (formalmente hablando, que dejen de ser clases y sean componentes), y valerte de los métodos WriteComponent y ReadComponent de un stream. Esto ya implementa, mas o menos, lo que explique antes (valiendose de la clase TWriter y TReader de la VCL).

En fin, este es un tema amplio, con lo dicho pretendo, mas que darte una solución, darte las ideas para que encontres una.

Hasta luego.


Hasta luego.

__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate
Responder Con Cita
  #3  
Antiguo 29-09-2006
Uoha Uoha is offline
Registrado
 
Registrado: sep 2006
Posts: 3
Poder: 0
Uoha Va por buen camino
Smile Iluminadora respuesta

Muchas gracias jachguate (nunca pensé que iba a tener una respuesta tan buena tan rápido ), entendí mi error... obviamente opté por la opción de heredar de TComponent . Sin embargo esta opción ya la había intentado y tampoco me había sido de utilidad, no la había podido implementar, y ahora volví a intentarlo con pocos resultados. Antes y después de postear vi que había muchos tutoriales sobre distintas maneras de hacer esto, pero me gustaría saber si existe una simple y breve que utilize el writeComponent y el readComponent. Estuve intentando y tampoco entiendo por qué no funciona lo siguiente:

Lector:

Código Delphi [-]
type
{...Declaración de la clase form y los procedimientos...}
var
  F:Finanzas;
  S:TFileStream;
  R:TReader;
  W:TWriter;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
  F := finanzas.Create(self);
  s := TFileStream.Create('C:\archivo',fmOpenRead);
  s.Position := 0;
  r := Treader.Create(s,4);
  r.Position := 0;
  r.Root := self;
  r.ReadComponent(F);
  r.free;
end;

Escritor:
Código Delphi [-]
procedure TForm1.FormCreate(Sender: TObject);

begin
  F := finanzas.Create(self);
  s := TFileStream.Create('C:\archivo',fmOpenRead);
  s.Position := 0;
  r := Treader.Create(s,4);
  r.Position := 0;
  r.Root := self;
  r.ReadComponent(F);
  r.free;
end;

(Por si es útil saberlo: el error surge en la parte de lectura, donde me dice que hubo un problema al leer el stream)

Otra vez me gustaría saber que estoy haciedno mal... también aceptaría un "no, realmente no hay una forma mucho más simple que la que escribió rounin en http://www.clubdelphi.com/foros/showthread.php?t=25835&highlight=writecomponent" (ya sé que es una forma genérica, pero armar algo más o menos con esa estructura sigue siendo... embrollado). También está la posibilidad de pasar de binnary a texito, de texto a archivo, y viceversa; pero prefería saber que no había otra más simple antes de rendirme por ella.


Gracias de nuevo.

Última edición por Uoha fecha: 29-09-2006 a las 07:46:40.
Responder Con Cita
  #4  
Antiguo 29-09-2006
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Poder: 27
jachguate Va por buen camino
Si ya tenes componentes, por que no llamar directamente a los métodos WriteComponente y ReadComponent del stream?

Código Delphi [-]
begin
  Conta := TConta.Create;
  Conta.Propiedad := Valor;
  Conta.OtraPropiedad := OtroValor;
  s := TFileStream.Create('c:\conta.dat', fmCreate);
  try
    s.WriteComponent(Conta);
  finally
    s.Free;
  end;

A mi me parece mucho mas limpio.

Ahora, ayer a partir de la charla, como me quedé algo picado con el tema, busqué un par de referencias y me encontré con la biblioteca RTTI Library, que creo te será de utilidad, con la ventaja que tus clases no tienen por que ser componentes.

No la he probado, pero tiene buena pinta y ya tiene procedimientos como SaveObjToIniFile que pueden serte de utilidad.

Hasta luego.

__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate
Responder Con Cita
  #5  
Antiguo 30-09-2006
Uoha Uoha is offline
Registrado
 
Registrado: sep 2006
Posts: 3
Poder: 0
Uoha Va por buen camino
Problema newbie, resuelto

Cita:
Empezado por jachguate
Si ya tenes componentes, por que no llamar directamente a los métodos WriteComponente y ReadComponent del stream?
Gracias , había probado con ese método y no lograba hacerlo andar.... hasta que vi que pusiste el ejemplo con propiedades y caí en que estaba usando fields, y que solo puedo exportar propiedades published (que poseen RTTI). Cambié todo a propiedades 'publicadas' y anduvo perfecto.

Voy a hecharle una ojeada al link.

Gracias!
Responder Con Cita
  #6  
Antiguo 14-05-2007
Avatar de juangiron
juangiron juangiron is offline
Miembro
 
Registrado: ene 2007
Posts: 26
Poder: 0
juangiron Va por buen camino
pregunta

hola... necesito guardar un objeto en algun tipo de archivo, la respuesta que diste no funciona por que existe una incompatibilidad de tipos Tcopmponent y Tobjeto (que es mi clase)... toca hacer algun tipo de casteo o algo asi?? si es asi como lo hago??
Responder Con Cita
  #7  
Antiguo 14-05-2007
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

En un "TObject" contarás con determinados que estarán también en la clase "TComponent". Porque "TComponent" hereda en última instancia de "TObject". Pero los métodos implementados por "TComponent" no están disponibles en "TObject" y clases derivadas de "TObject" que no hereden de "TComponent", claro.

La cuestión es que tal vez podrías heredar tu clase de "TComponent", en lugar de "TObject". De este modo ya podrías utilizar los métodos "LoadComponent" y "WriteComponent". No podrás hacerlo mientras tu clase no herede de "TComponent", a no ser que tú mismo te encarges de implementar métodos similares.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #8  
Antiguo 14-05-2007
Avatar de juangiron
juangiron juangiron is offline
Miembro
 
Registrado: ene 2007
Posts: 26
Poder: 0
juangiron Va por buen camino
PRegunra

hola logre guardar mis objetos que estan almacenados en un array asi:

Código Delphi [-]
procedure TFrmPrincipal.ToolButton14Click(Sender: TObject);
var
  FS: TFileStream;
  I:Integer;
begin
SaveDialog1.Filter:='Archivo XML(*.dat|*.DAT';
if SaveDialog1.Execute then
begin
   try
  FS := nil;
  try
    FS := TFileStream.Create(SaveDialog1.FileName, fmCreate);
    for I := 0 to High(ArrayObjetos) do
       FS.WriteComponent(ArrayObjetos[i].getObjeto);
  finally
    FS.Free;
  end;
  finally
   ShowMessage('Archivo Guardado');
  end;
  end;
end;

pero al hacer la funcion de cargar?

cual seria el Tobjet?

Código Delphi [-]
procedure TFrmPrincipal.ToolButton3Click(Sender: TObject);
var
  FS: TFileStream;
  newO:TObjeto;
  I:Integer;
begin
OpenDialog1.Filter:='Archivo dat(*.dat|*.DAT';
if OpenDialog1.Execute then
begin
   try
  FS := nil;
  try
    FS := TFileStream.Create( OpenDialog1.FileName, fmOpenRead );

   //  for I := 0 to   High(FS) do --> NEcesito hacer un FOR???
     FS.ReadComponent(TObjeto.create);
  finally
    FS.Free;
  end;
   finally

   end;
end;
end;

lo que quiero hacer es leer el archivo y meter estos datos en un array de objetos, debo hacer un for del FS?? como asigno el objeto a mi array para poder acceder a los metodos SET y GET de mi objeto (Tobjeto es mi clase de Objetos, no es igual a TObject)

gracias
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
Clase, objeto, tipo? [Gunman] OOP 3 04-01-2006 17:11:32
Como guardar un objeto en un archivo ? cmurua71 OOP 7 18-11-2005 22:26:30
Cargar Objeto Table jzk OOP 2 21-09-2005 13:51:51
Guardar y Cargar un reporte por código... emeceuy Impresión 3 30-12-2004 13:07:16
Controlar eventos de una clase propia keglevich OOP 4 15-09-2004 14:58:21


La franja horaria es GMT +2. Ahora son las 12:05:57.


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