Delphi-PRAXiS
Seite 1 von 4  1 23     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Textdatei laden - Integerüberlauf (https://www.delphipraxis.net/204925-textdatei-laden-integerueberlauf.html)

KWin 15. Jul 2020 06:53

Textdatei laden - Integerüberlauf
 
Hallo,

ich versuche mit einer StringList eine relativ große Text-Datei (1*265*819*892 Bytes) zu laden und
bekomme den Fehler "Integerüberlauf".
Compiliert unter Win64 mit Delphi 10.2 Tokyo.

gibt es da eine Lösung für das Problem?

lg Klaus

Dalai 15. Jul 2020 07:58

AW: Textdatei laden - Integerüberlauf
 
Wie sieht dein Code aus? Ohne ist das alles nur Glaskugelgucken.

Grüße
Dalai

KWin 15. Jul 2020 08:02

AW: Textdatei laden - Integerüberlauf
 
Der Code sieht ungefähr so aus:

Delphi-Quellcode:

var
  StrList : TStringList;

  StrList := TStringList.Create;
  try
    StrList.LoadFromFile(LogFileName);

  // ..
  // ..

  except
    on E: Exception do begin
      Info.Add(FormatLang('Fehler beim Öffnen der Datei: %s (%s)',[LogFileName,E.Message]));   // --> Integerüberlauf
    end;

  end;

hoika 15. Jul 2020 08:05

AW: Textdatei laden - Integerüberlauf
 
Hallo,
die TStringList hat eine Grenze von theoretisch 2 Mrd. Einträgen.
Praktisch ist aber schon viel früher Schluss.
Auch damals unter Delphi-64Bit ging es bei mir nicht weiter.

Ich hatte mir damals eine TLargeStringList gebaut,
die intern aus einzelnen StringListen bestand.
Grenze war dann trotzdem bei 1,5 GB Arbeitsspeicher (32-Bit-Delphi).

Bbommel 15. Jul 2020 08:12

AW: Textdatei laden - Integerüberlauf
 
Die Frage ist ja, was du mit dieser riesigen Datei anstellst. Ist es nötig, die komplett in den Speicher zu laden? Oder könntest du sie auch zeilenweise durchgehen und dafür z.B. einen TStreamReader benutzen?

Edit: Ach so, noch vergessen: ich vermute, dass der Fehler vielleicht auch gar nicht direkt in dem LoadFromFile bei dir auftritt, sondern in dem Code dazwischen, den du jetzt hier nicht gezeigt hast, weil du mit einem Integer durch die Zeilen oder Zeichen der StringList gehst oder irgendwas berechnest? Schau doch mal mit dem Debugger, wo der Fehler tatsächlich passiert. Das LoadFromFile selbst würde dir nämlich eher einen vollen Speicher melden, keinen Integerüberlauf (so meine Erfahrung mit zu großen Dateien).

Dalai 15. Jul 2020 08:22

AW: Textdatei laden - Integerüberlauf
 
Zitat:

Zitat von Bbommel (Beitrag 1469585)
ich vermute, dass der Fehler vielleicht auch gar nicht direkt in dem LoadFromFile bei dir auftritt, sondern in dem Code dazwischen, den du jetzt hier nicht gezeigt hast, weil du mit einem Integer durch die Zeilen oder Zeichen der StringList gehst oder irgendwas berechnest? Schau doch mal mit dem Debugger, wo der Fehler tatsächlich passiert.

Dieser Vermutung und der Empfehlung kann ich mich vollumfänglich anschließen.

Grüße
Dalai

Uwe Raabe 15. Jul 2020 08:25

AW: Textdatei laden - Integerüberlauf
 
Zitat:

Zitat von KWin (Beitrag 1469572)
ich versuche mit einer StringList eine relativ große Text-Datei (1*265*819*892 Bytes) zu laden

Das sind ja auch nur gut 180 MB, sollte also kein Problem sein.

Du solltest also wirklich mal den Debugger einsetzen.


Zitat:

Zitat von hoika (Beitrag 1469582)
die TStringList hat eine Grenze von theoretisch 2 Mrd. Einträgen.
Praktisch ist aber schon viel früher Schluss.
Auch damals unter Delphi-64Bit ging es bei mir nicht weiter.

Das LoadFromString/LoadFromStream ist in der Regel für die Begrenzung zuständig.
Delphi-Quellcode:
procedure TStrings.LoadFromStream(Stream: TStream; Encoding: TEncoding);
var
  Size: Integer;
  Buffer: TBytes;
begin
  BeginUpdate;
  try
    Size := Stream.Size - Stream.Position;
    SetLength(Buffer, Size);
    Stream.Read(Buffer, 0, Size);
    Size := TEncoding.GetBufferEncoding(Buffer, Encoding, FDefaultEncoding);
    SetEncoding(Encoding); // Keep Encoding in case the stream is saved
    SetTextStr(Encoding.GetString(Buffer, Size, Length(Buffer) - Size));
  finally
    EndUpdate;
  end;
end;
Obwohl Stream.Size und Stream.Position als Int64 deklariert sind, wird für die Differenz nur ein Integer bereitgestellt. Das nachfolgende SetLength muss dann noch einen zusammenhängenden Speicherbereich in der gewünschten Größe finden, was unter 32-Bit schnell mal zum problem werden kann. Aber auch dieses SetLength beschränkt die Puffergröße auf 2GB, weil NewLength auch nur ein Integer ist.

Allerdings sehe ich in diesem konkreten Fall erstmal keine dieser Grenzen überschritten.

KWin 15. Jul 2020 08:27

AW: Textdatei laden - Integerüberlauf
 
Ich denke auch, dass es nicht möglich ist via TStringlist eine so große Dateien zu laden.

Wenn mann sich die Procedure in System.Classes ansieht dann ist
beim Integer Schluss mit lustig.

Delphi-Quellcode:
procedure TStrings.LoadFromStream(Stream: TStream; Encoding: TEncoding);
var
  Size: Integer;
  Buffer: TBytes;
begin
  BeginUpdate;
  try
    Size := Stream.Size - Stream.Position;
    SetLength(Buffer, Size);
    Stream.Read(Buffer, 0, Size);
    Size := TEncoding.GetBufferEncoding(Buffer, Encoding, FDefaultEncoding);
    SetEncoding(Encoding); // Keep Encoding in case the stream is saved
    SetTextStr(Encoding.GetString(Buffer, Size, Length(Buffer) - Size));
  finally
    EndUpdate;
  end;
end;
Am Code dazwischen liegt es definitiv nicht.
ich werde das ganze umbauen und versuchen mit TStreamReader zu realisieren.

Danke für euer bemühen,
ich werde hier posten, wie ich es gelöst habe.

lg Klaus

KWin 15. Jul 2020 08:47

AW: Textdatei laden - Integerüberlauf
 
Habe das ganze mit TStreamReader gelöst.
Ich durchsuche viele Logfiles mit unterschiedlicher Dateigröße.
Wenn die Datei >= 1073741824 Bytes ist verwende ich den TStreamReader,
ansonsten die TStringList, welche wesentlich schneller ist.

hier mein Codeausschnitt

Delphi-Quellcode:

var
  StreamReader : TStreamReader;
  sLine : string;
  iLine : integer;


begin
  try
    StreamReader := TStreamReader.Create(LogFileName);
    iLine := 0;

    while not StreamReader.EndOfStream do begin
      Inc(iLine);
      sLine := StreamReader.ReadLine;


    // ..
    // ..
    // ..


    end;
  finally
    FreeAndNil(StreamReader);
  end;

end;

Uwe Raabe 15. Jul 2020 09:36

AW: Textdatei laden - Integerüberlauf
 
Zitat:

Zitat von KWin (Beitrag 1469601)
Wenn die Datei >= 1073741824 Bytes ist verwende ich den TStreamReader,
ansonsten die TStringList, welche wesentlich schneller ist.

Aber deine Datei ist doch gar nicht so groß:
Zitat:

Zitat von KWin (Beitrag 1469572)
ich versuche mit einer StringList eine relativ große Text-Datei (1*265*819*892 Bytes) zu laden

1*256*819*892 = 187.020.288


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:28 Uhr.
Seite 1 von 4  1 23     Letzte »    

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz