Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Escribir un objeto en un TFileStream (https://www.clubdelphi.com/foros/showthread.php?t=6968)

doverzhoff 29-01-2004 02:14:57

Escribir un objeto en un TFileStream
 
Hola a todos, tengo el siguiente código en C++:
Código:

class disco
{
  public:
    int codigo;
    char titulo[30], interprete[30];
    double costo;

    void menu();
    void captura();
    void muestra();
    void busca();
    void modifica();
    void elimina();
} x;

void disco::captura()
{
  cout << "Codigo    : ";
  cin >> codigo;
  cout << "Titulo    : ";
  gets(titulo);
  cout << "Interprete : ";
  gets(interprete);
  cout << "Costo      : ";
  cin >> costo;

  ofstream escritor("D:\\disco.txt", ios::app);
  escritor.write((char *)&x, sizeof(x));
  escritor.close();
}

void disco::muestra()
{
  ifstream lector("D:\\disco.txt");

  while(!lector.eof() && !lector.fail())
  {
    lector.read((char *)&x, sizeof(x));

    if(lector.eof())
      break;

    cout << "\nCodigo    : " << codigo;
    cout << "\nTitulo    : " << titulo;
    cout << "\nInterprete : " << interprete;
    cout << "\nCosto      : " << costo;
    cout << endl;
  }

  getch();
}

Es muy fácil escribir y leer todos los datos del objeto y deseo es saber si en Delphi se puede hacer lo mismo, en especial las siguientes lineas:
Código:

escritor.write((char *)&x, sizeof(x));
lector.read((char *)&x, sizeof(x));

He tratado de hacerlo de distintas maneras, pero no se cómo, ya que en el código de C++ no hay nada de constructores, sólo se lee el objeto desde el archivo y ya.

Aqui le muestro una de tantas formas con las cuales traté de hacerlo, pero no funciona (la clase no es la misma del código de C++):
Código:

unit JoyClassU;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

const arcDATOS = 'Clientes.txt';

type
  TNombre      = String[50];
  TDireccion  = String[100];
  TDescripcion = String[200];

  TCliente = class
  public
    Nombre      : TNombre;
    Deuda      : Integer;
    Direccion  : TDireccion;
    Descripcion : TDescripcion;
    constructor Create(Nom : TNombre; Deu : Integer; Dir : TDireccion;
                      Des : TDescripcion);
    procedure Guarda;
    function Busca(Nom : TNombre) : TStrings;
end;

implementation

constructor TCliente.Create(Nom : TNombre; Deu : Integer; Dir : TDireccion;
                  Des : TDescripcion);
begin
  inherited Create;
  Nombre := Nom;
  Deuda := Deu;
  Direccion := Dir;
  Descripcion := Des;
end;

procedure TCLiente.Guarda;
var
  Archivo : TFileStream;
begin
  Archivo := TFileStream.Create(arcDATOS, fmOpenReadWrite);
  Archivo.Seek(0, soFromEnd);
  Archivo.WriteBuffer(Self, SizeOf(TCliente));
  Archivo.Free;
end;

function TCLiente.Busca(Nom : TNombre) : TStrings;
var
  Archivo  : TFileStream;
  tsClientes : TStrings;
  inBandera  : Integer;
begin
  Archivo := TFileStream.Create(arcDATOS, fmOpenRead);
  tsClientes := TStringList.Create;
  while Archivo.Position < Archivo.Size do
  begin
    Archivo.ReadBuffer(Self, SizeOf(TCliente));
    ShowMessage(Nombre);
    if Pos(Nom, Nombre) <> 0 then
    begin
      inBandera := 1;
      tsClientes.Add(Nombre);
    end;
  end;
  Archivo.Free;
  Result := tsClientes;
end;

end.

Lo que hace la funcion Busca es devolver los nombres que fueron en contrados en todo en archivo.

Ojalá me haya dado a entender, lo que quiero saber, es cómo escribir y leer un objeto en un archivo, ando muy perdido :( . Saludos

dvz

delphi.com.ar 02-02-2004 16:13:25

Una solución fácil, aunque no muy óptima, es que tus objetos hereden de TComponent. Los streams tienen la facilidad de poder guardar los datos de un TComponent, esto esta hecho para poder leer y guardar los datos del DFM utilizando las clases TWriter y TReader:
Código:

var
  MiObjeto: TComponent;
begin
  FStream.WriteComponent(MiObjeto);
end;

El tema de guardar un objeto de cualquier clase, es que no todas las clases están compiladas para usar con RTTI, entonces lo único que nos queda es guardar el bloque de memoria que ocupa la clase, lo que no creo que sea muy viable, pues en la información del objeto en memoria, se apuntan muchas cosas por ejemplo direcciones a eventos, métodos... Lo mas normal cuando se quiere hacer algo así, es trabajar con registros planos, obviamente estos carecen de toda la funcionalidad de un objeto. Una solución viable, puede ser tener todos los datos que qiueras guardar de este objeto en un Record, y poder acceder a la dirección y tamaño de este, los que nos permitiría guardarlo sin ploblemas, sin necesitar de información que se volverá inmediatamente obsoleta (punteros a otras clases, eventos, métodos....)

Saludos!

doverzhoff 06-02-2004 02:39:13

Muchas gracias por su interés e información delphi.com.ar, lo del Record fué la opción que utilicé para solucionar la cuestión.

Nuevamente gracias.

dvz

jachguate 06-02-2004 04:00:33

Podes "especializar" las clases, creando un método WriteToStream que almacene toda la información que necesitas volver persistente, y un ReadFromStream que haga la misma función. O bien derivarlos de TPersistent y hacer un override de estos mismos métodos.

Hasta luego.

;)


La franja horaria es GMT +2. Ahora son las 08:33:04.

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