Link to home
Start Free TrialLog in
Avatar of Austin120998
Austin120998

asked on

Deleting Records

I can't work out the code for deleting and searching for records in random accsess files. I am using borlands |Turbo Pacal for windows 1.5. Ten points are up for grabbs from me, so be quick.
Avatar of vikiing
vikiing

As long as I know, you can not delete records from a random file; the only thing you can do is to "pack" the file, by moving records one space in order to overwrite the record you want to remove with something like this:

{ N = record number of record to be erased
  MaxRec = quantity of records in file }

For i:=n to MaxRec-1 do begin
    Seek(thisfile, i+1); Read(thisfile, thisrec);
    Seek(thisfile, i); Write(thisfile, thisrec);
end;

As long as I know, you can not delete records from a random file; the only thing you can do is to "pack" the file, by moving records one space in order to overwrite the record you want to remove with something like this:

N = record number of record to be erased
MaxRec = quantity of records in file

For i:=n to MaxRec-1 do begin
    Seek(thisfile, i+1); Read(thisfile, thisrec);
    Seek(thisfile, i); Write(thisfile, thisrec);
end;

After completion of that, last two records will be duplicated. Notice the file size remains THE SAME, because you don't have way to reclaim the space of the so deleted record. To have a scheme like this, you need to store the ACTUAL MaxRec into some portion of the file itself (record #0 is often used for that purpose), mainly because it's value can't be taken from Filesize().

How  I  H-A-T-E when an answer goes twice... ~~~~~~>:(

As long as I know, you can not delete records from a random file; the only thing you can do is to "pack" the file, by moving records one space in order to overwrite the record you want to remove with something like this:

N = record number of record to be erased
MaxRec = quantity of records in file

For i:=n to MaxRec-1 do begin
    Seek(thisfile, i+1); Read(thisfile, thisrec);
    Seek(thisfile, i); Write(thisfile, thisrec);
end;

After completion of that, last two records will be duplicated. Notice the file size remains THE SAME, because you don't have way to reclaim the space of the so deleted record. To have a scheme like this, you need to store the ACTUAL MaxRec into some portion of the file itself (record #0 is often used for that purpose), mainly because it's value can't be taken from Filesize().

Another way to do it is to make a field in the record that indicates its status (deleted,used..). For example, -1 could mean deleted and 1 could mean deleted.

This would mean only have to change one field, plus, when write out new records, you can use the space being occupied by deleted records.
Kellyjj: the problem of doing the way you suggest is that if you use a special search algorithm (i.e. a binary search), where records MUST be sorted, you must sort ALL records, no matter they have been logically deleted or not, with increase of process time.

Even a sequential search will have to check each record read to see if flag is present. Of course, it surely works; but I don't like it... :)
Avatar of kretzschmar
hi austin,

this is delphi code (full applcation with insert update delete next prev (not perfect!)), but you can pick out parts. i recommend that the file is unsorted, therefore i pick by deleting a record the last record in the file and write over the record which want to delete, then i go to the lastrecord and truncate there the file.


unit r_file_u;

interface

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

type
  TForm1 = class(TForm)
    BInsert: TButton;
    BUpdate: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    BPrev: TButton;
    BNext: TButton;
    BDelete: TButton;
    procedure FormCreate(Sender: TObject);
    procedure BInsertClick(Sender: TObject);
    procedure BUpdateClick(Sender: TObject);
    procedure BDeleteClick(Sender: TObject);
    procedure BNextClick(Sender: TObject);
    procedure BPrevClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

Type TheRec = Record
                Name1 : String[100];
                Name2 : String[100];
              end;
Var
  f : file of TheRec;
  r : TheRec;   {Buffer}
  cr : LongInt; {FileCursor}
  rc : LongInt; {RecordCount}
  tc : LongInt; {TempFileCursor}

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  assignfile(f,'MyFile.Dat');
  if not(fileexists('MyFile.Dat')) then
    rewrite(f)
  else
    reset(f);
  cr := 0;
  rc := fileSize(f) div sizeof(therec);
end;

procedure TForm1.BInsertClick(Sender: TObject);
begin
  r.name1 := edit1.Text;
  r.name2 := edit2.Text;
  seek(f,rc);
  write(f,r);
  inc(rc);
  cr := rc;
end;

procedure TForm1.BUpdateClick(Sender: TObject);
begin
  if cr > 0 then
  begin
    seek(f,cr-1);
    write(f,r);
  end;
end;

procedure TForm1.BDeleteClick(Sender: TObject);
begin
  if rc > 0 then      {Are there record in}
  begin
    if cr <> rc then  {CurrentCursor is not LastRecord }
    begin
      seek(f,rc-1);   {Goto LastRecord}
      read(f,r);      {Buffer LastRecord}
      seek(f,cr-1);   {Goto Record to deleted}
      write(f,r);     {Paste over LastRecord}
    end
    else              {The Record to delete is LastRecord}
    begin
      if rc > 1 then    {More then one Record}
      begin
        seek(f,rc - 2); {Goto the Record before LastRecord}
        read(f,r);      {Read for Output}
        cr := rc - 1;   {set CurrentCursor to Record before LastRecord}
      end
      else
      begin             {Last Record will be deleted : File then empty }
        r.Name1 := '';
        r.Name2 := '';
        cr := 0;
      end;
    end;
    seek(f,rc-1);     {Goto LastRecord}
    truncate(f);      {Truncate the file here}
    edit1.text := r.name1;  {Output }
    edit2.text := r.Name2;
    dec(rc);
  end;
end;

procedure TForm1.BNextClick(Sender: TObject);
begin
  if cr < rc then
  begin
    read(f,r);
    inc(cr);
    edit1.text := r.name1;
    edit2.text := r.Name2;
  end;
end;

procedure TForm1.BPrevClick(Sender: TObject);
begin
  if cr > 1 then
  begin
    seek(f,cr-2);
    read(f,r);
    dec(cr);
    edit1.text := r.name1;
    edit2.text := r.Name2;
  end;

end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  closefile(f);
end;

end.



meikl
ASKER CERTIFIED SOLUTION
Avatar of bobbyo
bobbyo

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
hi bobbyo,

you read your file by byte, not by record, your destination becomes shradder. On great files it will take time for deleting one record.

meikl