Solved

best way to isolate record # in a flat file.

Posted on 2001-08-21
8
132 Views
Last Modified: 2010-04-06
Ok folks. I'm writing a program that reads data from a datafile that is generated within the system. Since it's a standard delphi typed file handle, I am using filepos, filesize, and seek to move to record numbers. However, for some reason, my code keeps seeking me to record #0 or #1 or #2. I can never get to #2 or above. Here's an illustration of what I'm doing:

type datafilerecord = record
  deleted : boolean;
  first_name: string[30];
  last_name: string[30];
end;

In my function to move to the next record, I have this:

procedure TDvdCatForm.NextRecBtnClick(Sender: TObject);
var thefilepos : integer; // for debugging
begin
VerifySaveRec;
TheFilePos := filepos(moviefile); // for debugging
LoadRecord(filepos(moviefile)+1);
end;

The first time I press button named NextRecBtn, I get record #1 (ok), Next time I press the button, I could get #2 (ok) or I could get #1 again (WHAT!?)

Please don't tell me to use BDE or ODBC or anything. I have no experience in them and frankly I don't want to use them.

What am I doing wrong?

Thanks!
0
Comment
Question by:DanEgli
8 Comments
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6412237
you may seeking somewhere to another pos,
or you close and reopen your file somewhere
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6412273
maybe you should use a var for storing your current pos,
instead of seeking relative
0
 
LVL 3

Expert Comment

by:rondi
ID: 6412675
Hi,

Please show the code for VerifySaveRec and LoadRecord

rondi.
0
 
LVL 6

Expert Comment

by:wimmeyvaert
ID: 6412844
Is this flat file a line sequential file.
If so, then you could make a Schema-File (=recordlayout)
and use the file like a DB-Table (with the TTable-Comp).
You can then write Queries, Locate records, Move to records, Append Records, ... (Deletion of records is then not possible).

If you need a demo project, let me know.

Best regards,
The Mayor.
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 1

Author Comment

by:DanEgli
ID: 6413913
Ok. To answer the questions. It is not a line sequential. It is a file of records.

As far as storing current position in a var, thats fine, but I still need an efficent way to seek a particular record and then overwrite it.

Code for VerifySaveRec and LoadRecord:

procedure TDvdCatForm.VerifySaveRec;
begin
 if (itemunsaved) then
  if (Application.MessageBox('You have not saved this entry. Do you wish to save it now?', 'Exit Confirmation', MB_YESNO+MB_ICONQUESTION) = 6) then
    SaveScreenRecord;
end;


procedure TDvdCatForm.savescreenrecord;
begin
movie.deleted := dvdcatform.CheckBox1.Checked;
movie.Movie_ID := dvdcatform.MovieID.text;
movie.Title := dvdcatform.MovieName.Text;
movie.Format := dvdcatform.MovieFormat.ItemIndex;
movie.Genere := dvdcatform.MovieGenere.ItemIndex;
movie.Location := dvdcatform.MovieLocation.text;
if not filepos(moviefile) = filesize(moviefile) then
seek(moviefile, filepos(moviefile));
WRITE(moviefile, movie);
itemunsaved := false;
end;

procedure tDvdCatForm.loadrecord(recno: integer);
begin
  if (recno < 0) then
    begin
      ShowMessage('Cannot Move beyond top of file.');
      exit;
      end
    else if (recno > filesize(moviefile)-1) then
      begin
      ShowMessage('Cannot move beyond end of file.');
      exit;
    end;
  seek(moviefile, recno);
  read(moviefile, movie);
  dvdcatform.MovieID.text := movie.Movie_ID;
  dvdcatform.MovieName.text := movie.Title;
  dvdcatform.MovieFormat.ItemIndex := movie.Format;
  dvdcatform.MovieLocation.Text := movie.location;
  dvdcatform.MovieGenere.ItemIndex := movie.Genere;
  dvdcatform.OtherGenere.Text := movie.alt_genere;
  dvdcatform.CheckBox1.checked := movie.deleted;
  itemunsaved := false;
  if (length(movie.movie_id) < 6) then
  NewEntryMenuItemClick(Application);
end;
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6417903
your savescreenrecord do already overwrite the next record,
after the load the filecursor is behind the loaded record,
maybe you do duplicate/overwrite records unknown, which may cause the effect the rec#1 is near identical to rec#2

try this change(don't know if this applyable to your logic you use)

if not filepos(moviefile) = filesize(moviefile) then
//seek(moviefile, filepos(moviefile)); this may cause no seek
seek(moviefile, filepos(moviefile)-1);
WRITE(moviefile, movie);


i may also wroing in this case

meikl ;-)
0
 
LVL 1

Author Comment

by:DanEgli
ID: 6419859
Worth a shot. Thanks! I'll try it tonight.
0
 
LVL 27

Accepted Solution

by:
kretzschmar earned 50 total points
ID: 6420726
i've here a simple sample for a recordbased flatfile,
maybe you can adapt somewhat

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  //a record
                Name1 : String[100];
                Name2 : String[100];
              end;
Var
  f : file of TheRec;    // file of this record  
  r : TheRec;   {Buffer} // a memorybuffer for this record
  cr : LongInt; {FileCursor}  //Points to the current record in the file
  rc : LongInt; {RecordCount} //Holds the amount of records in the file

implementation

{$R *.DFM}

//open the file
procedure TForm1.FormCreate(Sender: TObject);
begin
  assignfile(f,'MyFile.Dat');  //we will work with this file
  if not(fileexists('MyFile.Dat')) then  //if this file not exists
    rewrite(f)  //create this file
  else
    reset(f);   //open this file
  cr := 0;      //
  rc := fileSize(f);
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
    r.name1 := edit1.text;
    r.name2 := edit2.text;
    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 ;-)
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Delphi 10 Seattle Dataset Actions 5 71
proper way to parse text with delphi 7 89
Delphi selector screen 2 58
Magic Software info 18 105
A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now