Einzelnen Beitrag anzeigen

Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.680 Beiträge
 
Delphi 5 Professional
 
#1

Effizientes Einlesen und Verarbeiten von Textdatei

  Alt 30. Jun 2022, 21:05
Hallo *.*.

Gegeben ist eine Textdatei, konkret im PEM-Format (BASE64 codiert). Ziel ist es, alle Blöcke dieser Datei einzulesen in ein Byte-Array - letztlich muss jeder Block in eine MSDN-Library durchsuchenCERT_BLOB-Struktur. Bisher mache ich das folgendermaßen:
Delphi-Quellcode:
procedure NameNotRelevant;
var
  Lsl: TMyStringList;
  LidxH, LidxF: integer;
  Lstr: string;
begin
    Lsl:= TMyStringList.Create;
    try
      Lsl.LoadFromFile(FFileName);
      repeat
          LidxH:= Lsl.IndexOf(PEM_HEADER);
          LidxF:= Lsl.IndexOf(PEM_FOOTER);
          if LidxH < 0 then
            NameNotRelevant2(Lstr)
          else begin
            Lstr:= Trim(Lsl.StringsBetween(LidxH+1, LidxF-1));
            NameNotRelevant2(Lstr);
            Lsl.DeleteMultiple(LidxF-LidxH+1, LidxH);
          end;
      until LidxH < 0;
    finally
      Lsl.Free;
    end;
end;

procedure NameNotRelevant2(const ACertStr: string);
var
  Lbin: TBytes;
  Lblob: CERT_BLOB;
begin
    if Length(ACertStr) = 0 then Exit;
    Lblob.cbData:= (Length(ACertStr)) * SizeOf(Char);
    SetLength(Lbin, Lblob.cbData);
    Move(ACertStr[1], Lbin[0], Lblob.cbData);
    Lblob.pbData:= LPByte(Lbin);
    // Do something with Lblob

(*    GetMem(Lblob.pbData, Lblob.cbData+1);
    try
      Move(ACertStr[1], Lblob.pbData, Lblob.cbData);
    finally
      FreeMem(Lblob.pbData);
    end;*)

end;
Die Methoden StringsBetween() und DeleteMultiple() hab ich ergänzt, und die Namen sollten selbsterklärend sein, aber sicherheitshalber hier noch deren Deklaration und Inhalt:
Delphi-Quellcode:
function TMyStringList.StringsBetween(AIndexFrom, AIndexTo: integer): string;
var
  i: integer;
begin
    Result:= '';
    if (AIndexFrom < 0) OR (AIndexTo >= Self.Count) then
        Exit;
    for i:= AIndexFrom to AIndexTo do
        Result:= Result + Self.Strings[i];
end;

function TMyStringList.DeleteMultiple(ACount: integer; AIndex: integer = 0): integer;
var
  i: integer;
begin
    Result:= -1;
    if (AIndex < 0) OR (AIndex >= Self.Count) then
        Exit;
    if (ACount >= Self.Count) then begin
        Result:= Self.Count;
        Clear;
    end else begin
        for i:= 1 to ACount do begin
            Self.Delete(AIndex);
            Inc(Result);
        end;
    end;
end;
Irgendwie finde ich die Sache ineffizent. Daher folgende Fragen:
  1. Kann man die Verarbeitung der Datei anders gestalten, beispielsweise mit einem Stream, und wenn ja, wie suche ich in einem solchen nach einem bzw. mehreren bestimmten Strings?
  2. Der Zwischenschritt über TBytes (= array of Byte) ist meiner Meinung nach unnötig. Irgendwie bin ich aber zu blöd, direkt auf Lblob.pbData den Speicher zu reservieren, die Bytes des Strings mit Move dorthin zu kopieren, und anschließend den Speicher mit FreeMem wieder freizugeben, ohne dass es knallt (siehe auskommentierter Teil). Ja, ich weiß, dass Move die Adresse des Zielspeichers ändert und es deshalb knallt. Wie kann ich denn sonst die Bytes des Strings dorthin übertragen?

Grüße
Dalai

Geändert von Dalai ( 1. Jul 2022 um 13:28 Uhr)
  Mit Zitat antworten Zitat