Author: Tomas Rutkauskas
I am trying to work out how to store approximately 1000 lines of text (3 columns,
30 chars each) inside an application. I do not want to have any .INI entries and
would prefer not to use an external file.
Answer:
You can start with one and embed it into a resource. Let's assume you have the data
in a normal textfile. Make a resource script file (filedata.rc) with a line like
FILEDATA RCDATA filedata.txt
Add this RC file to your Delphi 5 project group. This automatically gets you a $R
line for it in the project DPR file and the resource is compiled for you when you
build the project. Now, how to get at the data at runtime? Each line is a fixed
length of 90 characters. So the file could be represented as an array of records of
this type:
type
TFileData = packed record
col1, col2, col3: array[1..30] of Char;
crlf: array[1..2] of Char;
end;
PFileData = ^TFileData;
Let's use a class to regulate access to the data. I assume you only need to read
it, so there is no need to copy it from the resource.
1 type2 TDatahandler = class3 private4 FData: TList;
5 FResHandle: THandle;
6 function GetRecord(index: Integer): TFileData;
7 procedure GetRecordCount: Integer;
8 procedure InitDatalist;
9 public10 constructor Create;
11 destructor Destroy; override;
12 property Records[index: Integer]: TFileData read GetRecord;
13 property Recordcount: Integer read GetRecordcount;
14 end;
15 16 implementation17 18 constructor TDatahandler.Create;
19 begin20 inherited;
21 FData := TList.Create;
22 InitDatalist;
23 end;
24 25 destructor TDatahandler.Destroy;
26 begin27 Fdata.Free;
28 if FResHandle <> 0 then29 begin30 UnlockResource(FResHandle);
31 FreeResource(FResHandle);
32 end;
33 inherited;
34 end;
35 36 function TDatahandler.GetRecord(index: Integer): TFileData;
37 begin38 Result := PFileData(FData[i])^;
39 end;
40 41 procedure TDatahandler.GetRecordCount: Integer;
42 begin43 Result := FData.Count;
44 end;
45 46 procedure TDatahandler.InitDatalist;
47 var48 dHandle: THandle;
49 pData: PFileData;
50 numRecords, i: Integer;
51 begin52 pData := nil;
53 dHandle := FindResource(hInstance, 'FILEDATA', RT_RCDATA);
54 if dHandle <> 0 then55 begin56 numRecord := SizeofResource(hInstance, dHandle) div Sizeof(TFiledata);
57 FResHandle := LoadResource(hInstance, dHandle);
58 if FResHandle <> 0 then59 begin60 pData := LockResource(dHandle);
61 if pData <> nilthen62 begin63 FData.Capacity := NumRecords;
64 for i := 1 to Numrecords do65 begin66 FData.Add(pData);
67 Inc(pData);
68 end;
69 end70 else71 raise Exception.Create('Lock failed');
72 end73 else74 raise Exception.Create('Load failed');
75 end76 else77 raise Exception.Create('Resource not found');
78 end;
You can add a method to sort the FData list, for example, or a filter method that would populate another TList with pointer to records that match a set of criteria.