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.
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().
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().
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.
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... :)
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... :)
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
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
rewrite(f)
else
reset(f);
cr := 0;
rc := fileSize(f) div sizeof(therec);
end;
procedure TForm1.BInsertClick(Sender
begin
r.name1 := edit1.Text;
r.name2 := edit2.Text;
seek(f,rc);
write(f,r);
inc(rc);
cr := rc;
end;
procedure TForm1.BUpdateClick(Sender
begin
if cr > 0 then
begin
seek(f,cr-1);
write(f,r);
end;
end;
procedure TForm1.BDeleteClick(Sender
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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
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
{ 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;