AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Code-Bibliothek Neuen Beitrag zur Code-Library hinzufügen Delphi Daten in Datei einfügen bzw. löschen
Thema durchsuchen
Ansicht
Themen-Optionen

Daten in Datei einfügen bzw. löschen

Ein Thema von flow4.2 · begonnen am 9. Apr 2010 · letzter Beitrag vom 9. Apr 2010
Antwort Antwort
flow4.2

Registriert seit: 5. Sep 2007
5 Beiträge
 
#1

Daten in Datei einfügen bzw. löschen

  Alt 9. Apr 2010, 02:31
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...



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
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#2

Re: Daten in Datei einfügen bzw. löschen

  Alt 9. Apr 2010, 11:13
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
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#3

Re: Daten in Datei einfügen bzw. löschen

  Alt 9. Apr 2010, 11:58
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.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
flow4.2

Registriert seit: 5. Sep 2007
5 Beiträge
 
#4

Re: Daten in Datei einfügen bzw. löschen

  Alt 9. Apr 2010, 12:14
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ß
  Mit Zitat antworten Zitat
flow4.2

Registriert seit: 5. Sep 2007
5 Beiträge
 
#5

Re: Daten in Datei einfügen bzw. löschen

  Alt 9. Apr 2010, 12:45
@SirThornberry
Es wird jetzt TStream verwendet statt TFileStream...
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#6

Re: Daten in Datei einfügen bzw. löschen

  Alt 9. Apr 2010, 13:03
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.

Die Funktion von .Read und .Write bitte prüfen.
http://www.delphipraxis.net/internal...144663#1144663


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:
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;
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.

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.
$2B or not $2B
  Mit Zitat antworten Zitat
flow4.2

Registriert seit: 5. Sep 2007
5 Beiträge
 
#7

Re: Daten in Datei einfügen bzw. löschen

  Alt 9. Apr 2010, 15:59
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:
InsertData(BeispielStream, BeispielPos, BeispielLen, BeispielPointer as TStream)
  Mit Zitat antworten Zitat
flow4.2

Registriert seit: 5. Sep 2007
5 Beiträge
 
#8

Re: Daten in Datei einfügen bzw. löschen

  Alt 9. Apr 2010, 16:05
Achja...
Ich habe noch nie mit Class Helper gearbeitet, aber eigentlich müsste das doch so aussehen:
(also es funktioniert so auf jeden Fall )


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
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:28 Uhr.
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