![]() |
Text Dateien (500mb+) in einen String einlesen
hallo,
ich öffne mal einen neuen thread da es sich hier um ein anderes problem handelt ich habe vor eine sql dump datei in einen string einzulesen und bestimmte zeichenkombinationen zu entfernen bzw zu ersetzen, diese dateien sind mit unter einige hundert megabyte groß nachdem ich nun eine ganze weile im netz und hier im forum gesucht habe bin ich auf folgende units gestoßen die zu meiner freude wirklich extrem schnell zeichenketten ersetzen können ![]() schwierig ist das ganze allerdings weil durch die größe der dateien möglicherweise nicht ausreichend arbeitsspeicher auf dem system zur verfügung steht hat jemand damit evtl schonmal erfahrungen gesammelt und kann mir sagen wie ich die datei am besten in einen string lade? |
Re: Text Dateien (500mb+) in einen String einlesen
Ich habe einen Vorschlag, der nicht so viel Speicher braucht:
1) Erstelle eine Instanz TFileStream, mit der man auf deine Datei zugreifen kann. 2) Geh mit for durch den Stream. Nach x Delimiterzeichen oder y KB kopierst du diesen Teil des Streams in einen String. 3) Dieser String wird bearbeitet. 4) Den bearbeiteten String in einen neuen Stream speichern, der dann die bearbeiteten Daten enthält. Den ganzen String auf einmal zum bearbeiten zu laden wäre faktisch "Selbstmord" für den Rechner, denn so große Datenmengen benötigen erstens sehr viel Zeit zum laden/bearbeiten und zweitens belasten sie den Arbeitsspeicher des Rechners sehr stark. |
Re: Text Dateien (500mb+) in einen String einlesen
ich hatte es anfangs mit folgendem code probiert
Delphi-Quellcode:
allerdings gibts dann wie erwartet die fehlermeldung
F:=TFileStream.Create(FileName,fmOpenRead);
try SetLength(Dumplist,F.Size); F.ReadBuffer(Dumplist[1],F.Size); finally F.Free; end; Dumplist:= FastReplace(FastReplace(Dumplist,'[[', '', False),']]', '', False); F:=TFileStream.Create(FileName,fmCreate); try F.Write(Dumplist[1],Length(Dumplist)); finally F.Free; end; showmessage('done'); // Dumplist:= FastReplace(Dumplist,'[[', '', False); ich hätte zu wenig arbeitsspeicher |
Re: Text Dateien (500mb+) in einen String einlesen
Die Warnung kommt wahrscheinlich zu Recht:
Delphi-Quellcode:
Denn an den markierten Stelle erstellst du einen String der Länge F.Size, was in unserem Fall hier 500*1024*1024 = 524288000 Bytes sein sollte.
F:=TFileStream.Create(FileName,fmOpenRead);
try SetLength(Dumplist,F.Size); // Problem hier F.ReadBuffer(Dumplist[1],F.Size); // Oder hier finally F.Free; end; Dumplist:= FastReplace(FastReplace(Dumplist,'[[', '', False),']]', '', False); F:=TFileStream.Create(FileName,fmCreate); try F.Write(Dumplist[1],Length(Dumplist)); finally F.Free; end; showmessage('done'); // Dumplist:= FastReplace(Dumplist,'[[', '', False); |
Re: Text Dateien (500mb+) in einen String einlesen
ja leider, dafür hat man aber eine 2mb datei in weniger als 1 sekunde abgearbeitet
|
Re: Text Dateien (500mb+) in einen String einlesen
Wenn du nicht weisst wie groß deine Datei ist, musst du diese Einbußen in Kauf nehmen oder mehr Code schreiben, zum Beispiel eine Abfrage, die prüft, ob die Datei auf einmal verarbeitet werden kann.
|
Re: Text Dateien (500mb+) in einen String einlesen
naja ich hab leider noch nie so wirklich mit filestreams gearbeitet,
da muss ich erstmal grübeln wie ich da den häppchenportionierer aufsetze |
Re: Text Dateien (500mb+) in einen String einlesen
so dank der hilfe einiger dp mitglieder bin ich mittlerweile
schon so weit das ich den stream stückchenweise einlesen kann ich weiß nun allerdings nicht wie ich FastReplace auf den Buffer anwenden kann
Delphi-Quellcode:
try
SrcStream:=TFileStream.Create(FileName,fmOpenread or fmShareDenyNone); DestStream:=TFileStream.Create(FileName,fmCreate); GetMem(Buffer, 1024); try while (SrcStream.Position < SrcStream.Size) do begin if SrcStream.Size - SrcStream.Position > BlockSize then Len := BlockSize else Len := SrcStream.Size - SrcStream.Position; SrcStream.ReadBuffer(Buffer^, Len); //FastReplace(Buffer^,'[[', '', False); DestStream.WriteBuffer(Buffer^, Len); end; finally FreeMem(Buffer); end; finally SrcStream.Free; DestStream.Free; end; |
Re: Text Dateien (500mb+) in einen String einlesen
Delphi-Quellcode:
Siehe Kommentare.
try
SrcStream:=TFileStream.Create(FileName,fmOpenread or fmShareDenyNone); DestStream:=TFileStream.Create(FileName,fmCreate); GetMem(Buffer, 1024); try while (SrcStream.Position < SrcStream.Size) do //was ist mit dem letzten Byte? begin if SrcStream.Size - SrcStream.Position > BlockSize then //Was ist BlockSize? //Sonst kann ich nicht //weiterhelfen Len := BlockSize else Len := SrcStream.Size - SrcStream.Position; SrcStream.ReadBuffer(Buffer^, Len); //Rückgabewert speichern //ab hier würde ich nun weiter einlesen, aber überprüfen, ob die //zuletzt eingelesene SQL-Anweisung schon zu ende ist und dann nicht mehr //weiter einlesen, zu bisher gespeicherten Rückgabewert jeweils noch //dazuaddieren //Die Summe der Rückgabewerte ist nun die Anzahl der zu verarbeitenden //Bytes, bitte beachten //Buffer abarbeiten DestStream.WriteBuffer(Buffer^, Len); end; finally FreeMem(Buffer); end; finally SrcStream.Free; DestStream.Free; //wenn beim Erstellen des SrcStream ein Fehler auftritt, wurde DestStream noch nicht erstellt und es kommt zu einer AV end; |
Re: Text Dateien (500mb+) in einen String einlesen
blocksize ist wie folgt deklariert:
Delphi-Quellcode:
den rückgabewert aus readbuffer kann ich leider
const
BlockSize = 1024; nicht so einfach speichern
Delphi-Quellcode:
hier erhalte ich die fehlermeldung
Dumplist:= SrcStream.ReadBuffer(Buffer^, Len);
'inkompatible typen: string and procedure, untyped pointer or untyped parameter' |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:28 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz