我寫過一個單元來保存多個字符串列表。每個TStrings項目都存儲爲包含文本和表示對象的整數值的記錄。整個寫入二進制文件。以下是寫入數據的例程。我該如何傳遞一個字符串列表的名稱作爲參數
function AddToStream(Stream: TStream; Const pList: TStringList):Boolean;
Var idy: Integer;
TmpItem: tItemRec;
begin
TmpItem.pText := pList.ClassName; // Set up the Header
TmpItem.pObj := pList.Count * SizeOf(TmpItem); // Calc the # bytes for Stringlist
Stream.WriteBuffer(TmpItem, SizeOf(TmpItem)); // Write it to the Stream
for idy := 0 to plist.Count -1 do begin // Cycle through StringList
TmpItem.pText := pList[idy]; // Get the Text part
TmpItem.pObj := Integer(pList.Objects[idy]); // Get the Object part
Stream.WriteBuffer(TmpItem, SizeOf(TmpItem)); // Write record to stream
end;
end;
寫入流的第一條記錄意在攜帶一個名稱,用於標識字符串列表和後續文件中的字節數。顯然,在上面的代碼中,ClassName返回TStringList,我如何獲得傳遞的字符串列表的變量名,即MyStringList。
是否有可能從傳遞的標準字符串列表中派生它,或者我是否必須子類化字符串列表並向列表中添加一個VariableName屬性。
也許我應該顯示我的所有代碼。除了我最初的問題,我相信我的代碼至少可以用於單個TStringLists。直到我有一個決定要做什麼重命名問題,我還沒有測試過多個String列表。所以下面是完整的單位。
unit MultiFileUtils;
interface
Uses
System.SysUtils, System.Variants, System.Classes, Vcl.Dialogs, system.UITypes;
{This unit enables Multiple stringlist to be saved with objects to a single file
and reloaded the into the stringlists retaining their originla object value.
The stringlists you reload to should have classname as the stringlist you saved from
The data is held in a binary file, each string list has a aheader which holds
the ClassName of the stringlist and the length of the file. The text portion
of each entry in the stringlist should not exceed 255 characters.
Save functions return true if OK, AllowOverWrite doesn't check file already exists.
Read function returns true if OK, false if file not found or classname not found in file}
Function SaveLists(Const pLists: Array of TStringList; const pFileName: String; AllowOverwrite: Boolean): Boolean;
Function SaveList(Const pList: TStringList; const pFileName: String; AllowOverwrite: Boolean):Boolean;
Function ReadList(Const pFileName: String; Var pList: TStringList): Boolean;
procedure LoadTestData;
procedure SetUpTests;
procedure TestSave;
procedure TestRead;
Procedure ClearTests;
implementation
Type
tItemRec = record
pText: String[255];
pObj: Integer;
end;
{$ifDef Debug}
Var StrList1: TStringlist;
StrList2: TStringlist;
{$EndIf}
function CheckFileExists(pFileName: String):Boolean;
begin
if FileExists(pFileName) then
Result := (MessageDlg(pFileName + ' already exists, do you want to overwrite file?',
mtConfirmation, [mbYes,mbNo],0) = mrYes);
end;
function AddToStream(Stream: TStream; Const pList: TStringList):Boolean;
Var
idy: Integer;
TmpItem: tItemRec;
begin
TmpItem.pText := pList.ClassName; // Set up the Header
TmpItem.pObj := pList.Count * SizeOf(TmpItem); // Calc the # bytes for Stringlist
Stream.WriteBuffer(TmpItem, SizeOf(TmpItem)); // Write it to the Stream
for idy := 0 to plist.Count -1 do begin // Cycle through StringList
TmpItem.pText := pList[idy]; // Get the Text part
TmpItem.pObj := Integer(pList.Objects[idy]); // Get the Object part
Stream.WriteBuffer(TmpItem, SizeOf(TmpItem)); // Write record to stream
end;
end;
function SaveLists(Const pLists: Array of TStringList; Const pFileName: String;
AllowOverwrite: Boolean): Boolean;
Var
idx: Integer;
Stream: TStream;
begin
if AllowOverwrite then
Result := true
else
Result := CheckFileExists(pFileName);
if Result then begin
Stream := TFileStream.Create(pFileName, fmCreate); // Set up a fileStream
try
for idx := 0 to Length(plists) do // Loop through array of stringlists
AddToStream(Stream, pLists[idx]); // Add each Stringlist
finally
Stream.Free; // Write to disk and free Stream
end;
end;
end;
function SaveList(Const pList: TStringList; const pFileName: String;
AllowOverwrite: Boolean): Boolean;
Var
idx: Integer;
Stream: TStream;
begin
If AllowOverwrite then
result := true
else
Result := CheckFileExists(pFileName);
if Result then begin
Stream := TFileStream.Create(pFileName, fmCreate); // Set up filestream
try
AddToStream(Stream, pList); // Add Stringlist to stream
finally
Stream.Free; // Write to disk and free Stream
end;
end;
end;
function ReadList(Const pFileName: String; var pList: TStringList): Boolean;
Var idx: Integer;
Stream: TStream;
TmpItem: tItemRec;
Function NotEos: Boolean;
begin
Result := Stream.Position < Stream.Size;
end;
begin
Result := false;
if FileExists(pFileName) then begin
Stream := TFileStream.Create(pFileName, fmOpenRead);
Stream.Seek(0, soBeginning);
while NotEos do begin
if Stream.Read(TmpItem, SizeOf(TmpItem)) = SizeOf(TmpItem) then // Read Header
if TmpItem.pText = pList.ClassName then begin
Result := True; // Found header so file looks OK
idx := TmpItem.pObj; // Get the byte count
while (idx > 0) And NotEos do begin
Stream.ReadBuffer(TmpItem, SizeOf(TmpItem));
pList.AddObject(Trim(TmpItem.pText), Pointer(TmpItem.pObj));
Dec(idx);
end;
break;
end;
end;
Stream.Free;
end;
end;
{$ifDef Debug}
Procedure LoadTestData;
Var i: Integer;
begin
for i := 0 to 20 do begin
StrList1.AddObject('StrLst1 Data' + IntToStr(i), Pointer(i+1000));
StrList2.AddObject('StrLst2 Data' + IntToStr(i), pointer(i+2000));
end;
end;
procedure SetUpTests;
begin
StrList1 := TStringList.Create;
StrList2 := TStringList.Create;
LoadTestData;
end;
Procedure TestSave;
begin
SaveList(StrList1, 'MyTestFile.dat', true);
end;
Procedure TestRead;
begin
StrList1.Clear;
ReadList('MyTestFile.dat', StrList1);
end;
procedure ClearTests;
begin
StrList1.Free;
StrList2.Free;
end;
{$endif}
end.
顯示'tItemRec'的定義。編譯的exe文件不包含變量名稱。請解釋一下,如何在檢索過程中使用姓名信息? – MBo
變量名稱未編譯,編譯器在可執行代碼中不需要它們。他們是爲人類。 –
順便說一句,第二段可能意味着你認爲你正在寫流類的名稱。您不是,該流包含字符串和對象的地址。 –