![]() |
Daten in Datei einfügen bzw. löschen
Besonders wenn man große Dateien hat und diese nicht in den Arbeitsspeicher laden kann (will, darf, muss...) ist es nicht ohne weiteres möglich Daten an einer beliebigen Stelle der Datei einzufügen (bzw. zu löschen)...
InsertData fügt Daten an einer beliebigen Position in einen Stream ein Parameter: - Stream: Die Datei als TStream - P: Die Position an der die Daten eingefügt werden sollen - Len: Die Länge der Daten, die eingefügt werden sollen - Insert (optional): Die Daten die eingefügt werden sollen (wenn dieser Parameter nicht übergeben wird entsteht einfach ein "Loch" in der Datei - mit irgendwelchen Daten gefüllt) RemoveData löscht Daten an einer beliebigen Position in einem Stream Parameter - Stream: Die Datei als TStream - P: Die Position an der die Daten gelöscht werden sollen - Len: Die Länge der Daten, die gelöscht werden sollen - Removed (optional): Enthält die Daten die gelöscht wurden
Delphi-Quellcode:
procedure InsertData(Stream: TStream; const P, Len: Int64; Insert: TStream = nil);
const BufSize = $00010000; var Buf: PChar; N: Integer; Size, Z: Int64; begin GetMem(Buf, BufSize); try Z := 0; Size := Stream.Size; repeat if (Size-Z)-P < BufSize then N := (Size-Z)-P else N := BufSize; Stream.Position := Size-Z-N; Stream.ReadBuffer(Buf^, N); Stream.Position := Size-Z-N+Len; Stream.WriteBuffer(Buf^, N); Inc(Z, N); until (Size-Z) = P; if Insert <> nil then begin //Daten von Insert einfügen Stream.Position := P; Insert.Position := 0; if Len <= Insert.Size then Stream.CopyFrom(Insert, Len) else Stream.CopyFrom(Insert, 0); end; finally FreeMem(Buf, BufSize); end; end;
Delphi-Quellcode:
procedure RemoveData(Stream: TStream; P: Int64; const Len: Int64; Removed: TStream = nil);
const BufSize = $00010000; var Buf: PChar; N: Integer; begin GetMem(Buf, BufSize); try if Removed <> nil then begin //Daten, die gelöscht werden in Removed kopieren Stream.Position := P; Removed.Position := 0; Removed.CopyFrom(Stream, Len); end; repeat if Stream.Size-P-Len < BufSize then N := Stream.Size-P-Len else N := BufSize; Stream.Position := P+Len; Stream.ReadBuffer(Buf^, N); Stream.Position := P; Stream.WriteBuffer(Buf^, N); Inc(P, N); until P = Stream.Size-Len; Stream.Size := Stream.Size - Len; finally FreeMem(Buf, BufSize); end; end; Dies ist mein erster Post hier überhaupt, also bitte ich schon mal prophylaktisch um Nachsicht... :wink: jetzt wird TStream statt TFileStream verwendet Satt Read und Write wird jetzt ReadBuffer und WriteBuffer verwendet Optionale Paramter Insert und Removed hinzugefügt BufSize auf $00010000 gesetzt |
Re: Daten in Datei einfügen bzw. löschen
Hallo flow4.2,
könntest Du mir verraten wofür ExtendFile gut sein soll? Wenn eine Datei eine bestimmte Größe hat, und ich dort Daten einfügen will, dann tu ich das! Erst die Datei Vergrößern, und dann sie noch einmal anpacken um Daten dort hinein zu schreiben halte ich für nicht sehr effizent. Insbesonders, da ich zum Zeitpunkt des Vergrößerns schon genau wisen muß, wie groß die Daten sind, die ich einfügen will. Wenn Du schon Platz in einer Datei schaffen willst, solltest Du das aber auch mit definierten Werten tun, damit die Lücke ggf. wieder zu finden ist. Was Du machst, ist ja quasi eine verdoppelung der "Lückendaten". Gruß K-H |
Re: Daten in Datei einfügen bzw. löschen
Ich würde anstelle von TFileStream einfach nur TStream wählen. Denn ich sehe keinen Grund warum das nur auf TFileStream begrenzt sein soll. Eventuell baut sich jemand eine eigne TStream-Klasse welche auf Dateien zugreift und diese könnte es aktuell nicht nutzen.
|
Re: Daten in Datei einfügen bzw. löschen
Hallo p80286!
Naja, versuche doch mal in einen FileStream in der Mitte etwas einzufügen...dann überschreibst du natürlich Daten die dahinter kommen! Um das zu vermeiden vergrößerst du die Datei mit der Funktion ExtendFile direkt vorher, wobei eine Lücke genau an der Stelle erzeugt wird, an der du Daten einfügen willst. Beispiel: Du hast eine Datei (ich nehm jetzt mal ne Textdatei) in der steht: "Dies ist eine Datei..." Jetzt willst du den String "kleine " an die Position 14 einfügen, damit der Inhalt lautet "Dies ist eine kleine Datei..." Wenn du jetzt einfach an die Position 14 gehst und den String dort reinschreibst ergibt das ganze "Dies ist eine kleine .", da da " Datei.." von "kleine " überschrieben wird! Wenn du nun aber ExtendFile verwendest schaffst du praktisch vorher Platz für die Daten die du einfügen willst. Die Funktion verwendest du praktisch direkt vor dem einfügen --> da ist dir die Länge der einzufügenden Daten ja bekannt (Natürlich macht das ganze nur bei großen Dateien Sinn) Gruß |
Re: Daten in Datei einfügen bzw. löschen
@SirThornberry
Es wird jetzt TStream verwendet statt TFileStream... |
Re: Daten in Datei einfügen bzw. löschen
Erstmal das TStream, wie schon erwähnt, damit es vielseitiger verwendbar ist.
PS: man muß einen TStream auch nicht nur in einer TStream-Variable ablegen. :zwinker: Die Funktion von .Read und .Write bitte prüfen. ![]() Und ich würe bei beiden Funktionen noch zusätzlich einen weiteren (optionalen) Parameter einfügen. Einen weiteren TStream, welcher die Daten enthält/erhält, welche eingefügt oder entfernt werden sollen.
Delphi-Quellcode:
So könnte man auch gleichzeitig und über den selben Befehl die neuen Daten in die Lücke einfügen oder die entfernten Daten auslesen.
procedure InsertData(Stream: TStream; const P, Len: Int64;
Insert: TStream = nil); overload; procedure InsertData(Stream: TStream; const P: Int64; Len: Cardinal; Insert: Pointer); overload; procedure RemoveData(Stream: TStream; const P, Len: Int64; Removed: TStream = nil); overload; procedure RemoveData(Stream: TStream; const P: Int64; Len: Cardinal; Removed: Pointer); overload; Als Puffergröße sieht eine $00010000 (runde 64 KB) auch nicht sooo schlecht aus. PS: Das Ganze über eine Klasse zusammengefaßt oder gar als Class Helper für TStream wäre nicht verkehrt. |
Re: Daten in Datei einfügen bzw. löschen
So, hab jetzt mal Read und Write durch ReadBuffer und WriteBuffer ersetzt und die optionalen Parameter hinzugefügt
Ähm ich verstehe nicht ganz warum du die Procedure überlädst... Ist das nur um einen Pointer übergeben zu können? Da könnte man doch auch einfach folgendes aufrufen:
Delphi-Quellcode:
InsertData(BeispielStream, BeispielPos, BeispielLen, BeispielPointer as TStream)
|
Re: Daten in Datei einfügen bzw. löschen
Achja...
Ich habe noch nie mit Class Helper gearbeitet, aber eigentlich müsste das doch so aussehen: (also es funktioniert so auf jeden Fall :-D )
Delphi-Quellcode:
type
TStreamHelper = class helper for TStream public procedure InsertData(const Len: Int64; Insert: TStream = nil); procedure RemoveData(const Len: Int64; Removed: TStream = nil); end; ... procedure TStreamHelper.InsertData(const Len: Int64; Insert: TStream = nil); const BufSize = $00010000; var Buf: PChar; N: Integer; P: Int64; SSize, Z: Int64; begin GetMem(Buf, BufSize); try P := Position; Z := 0; SSize := Size; repeat if (SSize-Z)-P < BufSize then N := (SSize-Z)-P else N := BufSize; Position := SSize-Z-N; ReadBuffer(Buf^, N); Position := SSize-Z-N+Len; WriteBuffer(Buf^, N); Inc(Z, N); until (SSize-Z) = P; if Insert <> nil then begin //Daten von Insert einfügen Position := P; Insert.Position := 0; if Len <= Insert.Size then CopyFrom(Insert, Len) else CopyFrom(Insert, 0); end; finally FreeMem(Buf, BufSize); end; end; procedure TStreamHelper.RemoveData(const Len: Int64; Removed: TStream = nil); const BufSize = $00010000; var Buf: PChar; N: Integer; P: Int64; begin GetMem(Buf, BufSize); try P := Position; if Removed <> nil then begin //Daten, die gelöscht werden in Removed kopieren Position := P; Removed.Position := 0; Removed.CopyFrom(Self, Len); end; repeat if Size-P-Len < BufSize then N := Size-P-Len else N := BufSize; Position := P+Len; ReadBuffer(Buf^, N); Position := P; WriteBuffer(Buf^, N); Inc(P, N); until P = Size-Len; Size := Size - Len; finally FreeMem(Buf, BufSize); end; end; Die Daten werden an der aktuellen Position mit der Länge Len eingefügt bzw. gelöscht |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:55 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 by Thomas Breitkreuz