Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.144 Beiträge
Delphi 10.3 Rio
|
AW: Array of String in einer externen Datei speichern und laden
3. Dez 2020, 16:09
Hmm...
Schneller geht immer, oder?
Was ist wenn die Datei mit D6 oder D2007 erzeugt wurde und in XE eingelesen werden muss...
32Bit Schreiben, 64 Bit Lesen hab ich nicht berücksichtig. Ginge aber auch indem man aus Integer Int32 macht..
Wir gehen mal davon aus, dass die Datei nicht 2TB groß ist, oder defekt... (Könnte man natürlich alles abfangen)
Bisschen "Schön-Wetter-Code" gefällig?
Delphi-Quellcode:
program Project378;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils
, System.Classes
;
Procedure Schreibe( Const aBzB : TArray< String>);
var
CharSize : byte;
Anz,
L,
I : Integer;
MS : TMemoryStream;
P : Pointer;
PP : NativeUInt absolute P;
begin
MS := TMemoryStream.Create;
try
Anz := Length(aBzB);
CharSize := Sizeof(Char);
L := 0;
for i:=0 to Anz-1 do
inc(L,Length(aBzB[i]) * CharSize);
MS.SetSize(Sizeof(Anz)+1+Anz*Sizeof(Integer)+L);
MS.Position := 0;
P := MS.Memory;
Move(Anz,P^,Sizeof(Anz));
inc(PP,Sizeof(Anz));
Move(CharSize,P^,1);
inc(PP);
for i:=0 to high(aBZB) do
begin
L := Length(aBzB[i]);
Move(L,P^,Sizeof(L));
inc(PP,Sizeof(L));
L := L * CharSize;
Move(aBzB[i][1],P^,L);
inc(PP,L);
end;
MS.SaveToFile(' Daten.Dat');
finally
MS.Free;
end;
end;
{.$DEFINE CanDoAnsiRead}
Procedure Lese( Var aBzB : TArray< String>);
var
CharSize : byte;
Anz,
L,
I : Integer;
MS : TMemoryStream;
Len : TArray<Word>;
P : Pointer;
PP : NativeUInt absolute P;
{$IFDEF CanDoAnsiRead}
S : AnsiString;
AnsiRead : boolean;
{$ENDIF}
begin
{$IFDEF CanDoAnsiRead}
AnsiRead := false;
{$ENDIF}
MS := TMemoryStream.Create;
try
MS.LoadFromFile(' Daten.dat');
MS.Position := 0;
P := MS.Memory;
Move(P^,Anz,Sizeof(Anz));
Inc(PP,Sizeof(Anz));
Move(P^,CharSize,1);
inc(PP);
if (CharSize <> Sizeof(Char)) then
{$IFDEF CanDoAnsiRead}
if (CharSize = 1)
then AnsiRead := true
else {$ENDIF}
raise Exception.Create(' Daten wurden mit eine Unicode Delphi Version erzeugt'); // Könnte man ggf. in Widestrings einlesen...
Setlength(aBzB,Anz);
for i:=0 to Anz-1 do
begin
Move(P^,L,Sizeof(L));
inc(PP,Sizeof(L));
{$IFDEF CanDoAnsiRead}
if AnsiRead
then begin
Setlength(S,L);
Move(P^,S[1],L);
inc(PP,L);
aBzB[i] := S; // UTF8?
end
else begin {$ENDIF}
Setlength(aBzB[i],L);
Move(P^,aBzB[i][1],L*CharSize);
inc(PP,L*CharSize);
{$IFDEF CanDoAnsiRead} end; {$ENDIF}
end;
finally
MS.Free;
end;
end;
Var
BzBSource,
BzBDest : TArray< String>;
I : Integer;
begin
try
BzBSource := [' Frank',' Peter',' Klaus',' Sebastian'];
Schreibe(BzBSource);
Lese(BzBDest);
if Length(BzBDest) <> Length(BzBSource) then
Raise Exception.Create(' Source <> Dest');
for i:=0 to high(BzBSource) do
if BzBSource[i] <> BzBDest[i] then
Raise Exception.Create(' Daten unterschiedlich!');
except
on E: Exception do
Writeln(E.ClassName, ' : ', E. Message);
end;
end.
Oder so...
Mavarik
|