Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

best way to isolate record # in a flat file.

Posted on 2001-08-21
8
Medium Priority
?
141 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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
 
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 150 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

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
This course is ideal for IT System Administrators working with VMware vSphere and its associated products in their company infrastructure. This course teaches you how to install and maintain this virtualization technology to store data, prevent vuln…
In this brief tutorial Pawel from AdRem Software explains how you can quickly find out which services are running on your network, or what are the IP addresses of servers responsible for each service. Software used is freeware NetCrunch Tools (https…
Suggested Courses

670 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