Mostrando entradas con la etiqueta ReWrite. Mostrar todas las entradas
Mostrando entradas con la etiqueta ReWrite. Mostrar todas las entradas

sábado, 8 de agosto de 2020

Guardar y leer un array of integer en un archivo.

Un vector de números enteros lo podemos también guardar en un archivo de texto, al fin y al cabo no hay que complicarse con la separación decimal y con un IntToStr para guardar y un StrToInt para leer, no debería de haber ninguna complicación, en más, dependiendo de lo que se busque, hasta tiene la ventaja de poder leerse y editar con un editor de texto plano, claro que también esto puede se una desventaja.

En Pascal podemos manejar archivos de varias formas, a su vez los archivos pueden ser de texto o binarios. Dentro del tipo de los binario tenemos binario a secas o de algún tipo, como por ejemplo, de enteros, de registros, etc.

En el ejemplo se usa el vector1 del tipo dinámico (también se puede usar uno estático) al cual se le establece un rango de 100 elementos, al ser dinámico se basa en cero, por lo tanto su índice inicial es el 0 y el final el 99; a este array se le cargan número enteros aleatorios hasta el 5.000 (se pude cambiar por cualquier otro valor). Luego se lo guarda en un archivo, se muestra el contenido en Memo1.

El vector2 se usa para leer el archivo de enteros. ¿Era necesario usar 2 vectores? No, se podría usar uno solo, pero pienso que se visualiza mejor el ejemplo. El vector2 se muestra en el Memo2 para comparar el resultado obtenido.

Lo principal:

  • Para crear/cargar el archivo usamos: file of Integer.
  • Para grabar el array abrimos/creamos el archivo con Rewrite que si el archivo existe lo sobre escribe. Recorremos el vector de la forma clásica y grabamos cada elemento del mismo en el archivo mediante Write.
  • Para leer el archivo lógicamente también necesitamos definir una variable del tipo File Of Integer, abrimos el archivo mediante Reset que es de solo lectura y con un ciclo for to lo leemos y cargamos en vector2 mediante Read.
  • Siempre debe cerrarse el archivo usando CloseFile.

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Buttons, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    BCargarArray: TBitBtn;
    BGuardarArray: TBitBtn;
    BLeerArray: TButton;
    Edit1: TEdit;
    Memo1: TMemo;
    Memo2: TMemo;
    procedure BCargarArrayClick(Sender: TObject);
    procedure BGuardarArrayClick(Sender: TObject);
    procedure BLeerArrayClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure FormCreate(Sender: TObject);
  private
    procedure ArrayToFile(aArray:array of integer; aNameFile:String);
    procedure ArrayFromFile(aArray:array of integer; aNameFile:String);
  public

  end;

var
  Form1: TForm1;
  vector1, vector2:array of integer;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
  SetLength(vector1,100);
  SetLength(vector2,100);
end;

procedure TForm1.BGuardarArrayClick(Sender: TObject);
begin
  ArrayToFile(vector1,Edit1.Text);
end;

procedure TForm1.BLeerArrayClick(Sender: TObject);
begin
  ArrayFromFile(vector2,Edit1.Text);
end;

procedure TForm1.ArrayToFile(aArray: array of integer; aNameFile: String);
var
  i:Integer;
  aFile:file of Integer;
begin
  AssignFile(aFile,aNameFile);
  Rewrite(aFile);
  for i:=Low(aArray) to High(aArray) do
    Write(aFile,aArray[i]);
  CloseFile(aFile);
end;

procedure TForm1.ArrayFromFile(aArray: array of integer; aNameFile: String);
var
  i:Integer;
  aFile:file of Integer;
begin
  Memo2.Clear;
  AssignFile(aFile,aNameFile);
  Reset(aFile);
  for i:=1 to 100 do
    begin
      Read(aFile,aArray[i-1]);
      Memo2.Lines.Add((IntToStr(aArray[i-1])));
    end;
  CloseFile(aFile);
end;

procedure TForm1.BCargarArrayClick(Sender: TObject);
var
  i:Integer;
begin
  Memo1.Clear;
  for i:=Low(vector1) to High(vector1) do
    begin
      vector1[i]:=i+Random(5000);
      Memo1.Lines.Add(IntToStr(vector1[i]));
    end;
end;

procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  CloseAction:=caFree;
end;

end.

Descargar el proyecto.

domingo, 11 de marzo de 2018

Guardar y leer registros en archivos binarios.

Hay dos maneras de hacer esto, con AssingFile o con TFileStream. Prefiero AssingFile, pues se pueden hacer cosas que no se pueden con stream, por ejemplo mover el puntero hacia un registro (aunque solo en modo lectura) mediante el procedimiento Seek y también podemos usar la función FilePos para averiguar sobre qué registro está el puntero. Agregar datos a un archivo binario no se puede ni con AssigFile ni con FileStream, siempre debemos cargar los datos en memoria y re-escribir todo el archivo, lo cual hoy no es la gran cosa debido a la cantidad de sobra de memoria RAM que tiene cualquier ordenar y la velocidad de procesamiento.

En este ejemplo guardaremos registros con nombres de empresas, número ID y nombre de la base de datos, algo simple. Como buffer usaremos un array (vector o matriz unidimensional) de registros.

Código:

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
    Classes, SysUtils, FileUtil, Forms, Controls, Graphics,
    Dialogs, StdCtrls;

type

  { TForm1 }

    TForm1 = class(TForm)
    BGuardar: TButton;
    BLeer: TButton;
    BAgregar: TButton;
    edID: TEdit;
    EdEmpresa: TEdit;
    EdBD: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Memo1: TMemo;
    procedure BAgregarClick(Sender: TObject);
        procedure BGuardarClick(Sender: TObject);
      procedure BLeerClick(Sender: TObject);
        procedure FormCreate(Sender: TObject);
    private
        { private declarations }
    public
        { public declarations }
    end;
type
    TReg=record
      ID:Integer;
      Empresa:string[100];
      BD:string[100];
  end;

var
    Form1: TForm1;
    archivo:String;
    aReg:array[0..99] of TReg;
    cantReg:Integer;


implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  archivo:=GetCurrentDir+PathDelim+'datareg.bin';
  cantReg:=0;
  if FileExists(archivo) then BLeerClick(Sender);
  //Si el archivo existe lo carga al array
end;

procedure TForm1.BGuardarClick(Sender: TObject);
var
  FReg:File of TReg; //Archivo que contendrá registros tipo TReg
  i:Integer;
begin
  AssignFile(FReg,archivo);  //Vinculamos el archivo
  Rewrite(FReg);             //Lo vamos a sobreescribir
  for i:=0 to cantReg-1 do //Recorremos el array y lo escribimos
                           //con Write
  begin
    Write(FReg,aReg[i]);
 end;
  CloseFile(FReg);   //Cerramos el archivo
end;

procedure TForm1.BLeerClick(Sender: TObject);
var
  FReg:File of TReg; //Archivo que contendrá registros tipo TReg
  i:Integer;
begin
  AssignFile(FReg,archivo); //Vinculamos el archivo
  Reset(FReg); //Lo abrimos en modo solo lectura
  i:=0;
  while not (EOF(FReg)) do      //Lo cargamos al array
  begin
    Read(FReg,aReg[i]);
    Memo1.Lines.Add(IntToStr(aReg[i].ID)+' '+aReg[i].Empresa+' '+
    aReg[i].BD);
    Inc(i);
    Inc(cantReg);
  end;
  CloseFile(FReg);  //Cerramos el archivo
end;

procedure TForm1.BAgregarClick(Sender: TObject);
begin
  aReg[cantReg].ID:=StrToInt(edID.Text);//Agregamos solo al array, 
                                        //no al archivo.
  aReg[cantReg].Empresa:=EdEmpresa.Text;
  aReg[cantReg].BD:=EdBD.Text;
  Inc(cantReg);
  Memo1.Lines.Add('aReg['+IntToStr(cantReg-1)+']: '+EdEmpresa.Text);
end;

end.


En el registro debemos definir la longitud de los strings.
El primer registro de un archivo binario está en la posición 0 (cero).
No hay forma de agregar un registro a un archivo binario, como sí podemos hacerlo con archivos de texto plano, siempre ha que sobreescribir todo el archivo, de ahí ReWrite.
Al utilizar AssignFile podemos acceder mediante Seek a un determinado registro conociendo su posición y leerlo.

Código fuente:  archivosbinarios.7z (incluye e archivo binario con 5 registros).

o en GitLab