Files of Records

The program SaveRecordArray hard codes some data into an array of records for convenience and then saves each record to a file that it creates. (If a file of the same name exists it will be overwritten). For records that are to be saved, it is important that the length of each string field is given in square brackets after the word string in the definition of the record type. This ensures that the record size is fixed. After you run the program you can open up the file marks.txt in any text editor and check the string fields.

Note: In Delphi 7 but not Lazarus, these programs generate an unsafe type error message about the file. The help file states, "You have used a data type or operation for which static code analysis cannot prove that it does not overwrite memory. In a secured execution environment such as .NET, such code is assumed to be unsafe and a potential security risk." Please let us know if the programs fail to run on your system.
program SaveRecordArray;
{$APPTYPE CONSOLE}
uses
  SysUtils;
type
  TStudent = record
    Forename, Surname : string[15];
    TheoryMark, PracticalMark : integer;
  end;
const
  MAX = 3;
var
  Students : array[1 .. MAX] of TStudent;
  Count : integer;
  StudentFile : file of TStudent;
begin
  with Students[1] do
    begin
      Forename := 'Jo';
      Surname :='Wood';
      TheoryMark := 55;
      PracticalMark := 66;
    end;
  with Students[2] do
    begin
      Forename := 'John';
      Surname := 'Bode';
      TheoryMark := 73;
      PracticalMark := 58;
    end;
  with Students[3] do
    begin
      Forename := 'Kapil';
      Surname := 'Shah';
      TheoryMark := 59;
      PracticalMark := 58;
    end;
  assignFile(StudentFile, 'marks.txt');
  rewrite(StudentFile);
  writeln('Writing records to marks.txt');
  for Count := 1 to MAX do
    begin
      write(StudentFile, Students[Count]);
    end;
  closeFile(StudentFile);
  readln;
end. 

In order to load records from a file, you must define exactly the same type of record as that in the file. If you have the program that created the file, you can do a lot of copying and pasting to create the new program. When reading from a file you must reset it and certainly not rewrite it. If you know how many records are in the file you can use a for loop to read the records, but the while loop in the following program is more versatile and counts the records as it reads them.

Note: Run the program SaveRecordArray to create the text file before running this program.
program LoadRecordArray;
{$APPTYPE CONSOLE}
uses
  SysUtils;
type
  TStudent = record
    Forename, Surname : string[15];
    TheoryMark, PracticalMark : integer;
  end;
const
  MAX = 100;  //A safe limit for the number of possible records.
var
  Students : array[1 .. MAX] of TStudent;
  NumberOfRecords, Count : integer;
  StudentFile : file of TStudent;
begin
  assignFile(StudentFile, 'marks.txt');
  reset(StudentFile);
  writeln('Reading records from marks.txt');
  NumberOfRecords := 0;
  while not eof(StudentFile) do
    begin
      inc(NumberOfRecords);
      read(StudentFile,Students[NumberOfRecords]);
    end;
  closeFile(StudentFile);
  writeln('NumberOfRecords: ', NumberOfRecords);
  //Display records 
  for Count := 1 to NumberOfRecords do
    begin
      writeln;
      with Students[Count] do
        begin
          writeln('Name: ', ForeName,' ', Surname);
          writeln('Theory Mark: ', TheoryMark);
          writeln('Practical Mark: ', PracticalMark);
        end;
    end;
  readln;
end.

A good way to read an individual record is to use the seek procedure. Seek the record number you require, noting that the numbering starts at 0, then read the record. When the record is read, the internal pointer is positioned to read the following record or the end of file marker. In order to save an edited record to its original position, you can use the seek procedure with the same parameter as you used to locate the record. The following program allows the user to select any of the records, view it, then edit one of its fields.

Note: Run the program SaveRecordArray to create the text file before running this program.
program SeekRecord;
{$APPTYPE CONSOLE}
uses
  SysUtils;
type
  TStudent = record
    Forename, Surname : string[15];
    TheoryMark, PracticalMark : integer;
  end;
var
  TempStudent : TStudent;
  RecordNumber, Choice : integer;
  StudentFile : file of TStudent;
begin
  assignFile(StudentFile, 'marks.txt');
  reset(StudentFile);
  write('Which record would you like to view/edit (1 - 3)? ');
  readln(RecordNumber);
  seek(StudentFile, RecordNumber - 1);
  read(StudentFile, TempStudent);
  //Display record
  with TempStudent do
    begin
      writeln('Name: ',ForeName,' ', Surname);
      writeln('Theory Mark: ', TheoryMark);
      writeln('Practical Mark: ', PracticalMark);
    end;
  writeln;
  //Edit
  writeln('Do not edit (Type 0), Edit Forename (1), Surname (2),');
  write('Theory Mark (3) or Practical Mark (4) ');
  readln(Choice);
  case Choice of
    1 : begin
          write('Forename? ');
          readln(TempStudent.Forename);
         end;
    2 : begin
          write('Surname? ');
          readln(TempStudent.Surname);
        end;
    3 : begin
          write('Theory Mark? ');
          readln(TempStudent.TheoryMark);
        end;
    4 : begin
          write('Practical Mark? ');
          readln(TempStudent.PracticalMark);
        end;
  end;
  if Choice > 0 then
    begin
      seek(StudentFile, RecordNumber - 1);
      write(StudentFile, TempStudent);
    end;
  closeFile(StudentFile);
  readln;
end. 

Programming - a skill for life!

Single records and arrays and files of records