Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Datei teilweise kopieren (https://www.delphipraxis.net/56391-datei-teilweise-kopieren.html)

Schwedenbitter 4. Nov 2005 22:15


Datei teilweise kopieren
 
Hallo,

ich habe ein Problem für das ich bislang keine Lösung habe finden können:

Ich möchte aus einer Quelldatei byteweise Daten in eine Zieldatei kopieren. Allerdings möchte ich nicht die gesamte Datei kopieren, sondern nur bestimmte Teile. Hierzu habe ich im Vorhinein die Datei durchsucht und die Anfangspositionen und Längen der Teile ermittelt, die nicht kopiert werden sollen. Der Benutzer soll zusätzlich noch auswählen können, welche Daten nicht mit übernommen werden sollen.

Ich hatte schon die Idee über einen Zähler die Position mit aufzuzeichnen und die Sache etwa so zu lösen:

Delphi-Quellcode:
Byte:=0;
While Not EOF(FromFile) Do
Begin
   Read(FromFile,Byte);
   Case P Of
      Start1..Ende1 : If Not CheckBox1.Checked Then Write(ToFile,Byte);
      Start2..Ende2 : If Not CheckBox2.Checked Then Write(ToFile,Byte);
      Start3..Ende3 : If Not CheckBox3.Checked Then Write(ToFile,Byte);
      .
      .  // Wenn nicht zum löschen ausgewählt,
      .  // nur dann kopieren!
   End;
   Inc(P);
End;
Das dumme ist nur, dass bei den Case oder X in [Y..Z] Abfragen keine Variablen zulässig sind, was diesen Versuch nicht glücken lässt.

Hat jemand eine Idee?
Ich schätze, dass es hierfür sogar schon eine Lösung im Forum gibt und ich mich nur zu dumm angestellt habe, sie zu finden.

neolithos 5. Nov 2005 03:46

Re: Datei teilweise kopieren
 
Delphi-Quellcode:
Byte:=0;
While Not EOF(FromFile) Do
Begin
   Read(FromFile,Byte);
   if ((P >= Start1) and (P <= Ende1) and not CheckBox1.Checked) or
       (P >= Start2) and (P <= Ende2) and not CheckBox2.Checked) or
       (P >= Start3) and (P <= Ende3) and not CheckBox3.Checked) or
       ...) then
     Write(ToFile,Byte);
   Inc(P);
End;
Eventuell so?

Schwedenbitter 5. Nov 2005 10:11

Re: Datei teilweise kopieren
 
Danke für die schnelle Antwort.

Im Prinzip funktioniert das ganze exakt so, wie es meinem Quellcodevorschlag zu entnehmen war. Nur habe ich dort leider was entscheidendes vergessen:

Es soll nämlich immer dann, wenn die Position nicht in die fraglichen Bereiche fällt, kopiert werden. Bei der Case Anweisung fehlt daher am Ende noch ein Else Write(ToFile,Byte);.
Im Moment ist es leider so, dass von den ausgewählten Bereichen die gewünschten kopiert und die unerwünschten weggelassen werden. Das hat mich schonmal ein Stück weiter gebracht, weil ich so feststellen konnte, das meine Endwerte (EndeX) nicht exakt waren. Allerdings wird alles andere auch nicht kopiert.

Ich hatte schon an verschachtelte If Schleifen gedacht aber schnell festgestellt, dass er die übrigen 2 Bereiche nicht mehr prüft, wenn der Wert nicht mehr unter die erste Bedingung fällt.

Schwedenbitter 5. Nov 2005 18:18

Re: Datei teilweise kopieren
 
Ich habe jetzt die (bzw. eine mögliche) Lösung gefunden. Ich muss mich insoweit korrigieren, als es doch mit verschachtelten If Schleifen funktioniert. Für den Fall, dass jemand Interesse haben sollte, habe ich den Quelltext der Lösung gleich noch mal beigefügt.

Jetzt wüsste ich nur gern noch, ob jemand eine Idee hat, wie man das ganze schneller machen könnte und ob man das Begin und End weglassen kann, in die ich jeweils die Abfrage If Not IDv?.Checked Then Write(TF,BDummy); eingefasst habe.

Hier der Quelltext:

Delphi-Quellcode:
P:=0;
While Not EOF(FF) Do
Begin
   Read(FF,BDummy);
   If (P>=V1Pos) And (P<=V1Size) Then
   Begin
      If Not IDv1.Checked Then Write(TF,BDummy);
   End
   Else
   Begin
      If (P>=V2Pos) And (P<=V2Size) Then
      Begin
         If Not IDv2.Checked Then Write(TF,BDummy);
      End
      Else
      Begin
         If (P>=VLPos) And (P<=VLSize) Then
         Begin
            If Not IDvL.Checked Then Write(TF,BDummy);
         End
         Else
         Begin
            If (P>=VAPos) And (P<=VASize) Then
            Begin
               If Not IDvA.Checked Then Write(TF,BDummy);
            End
            Else Write(TF,BDummy);
         End;
      End;
   End;
End;

marabu 5. Nov 2005 19:16

Re: Datei teilweise kopieren
 
Wenn ich die Bereitstellung der nicht zu kopierenden Bereiche außen vor lasse (weil eine Frage der Benutzerschnittstelle), dann könnte ich mir die Erzeugung der Ausgabedatei auch so vorstellen:

Delphi-Quellcode:
type
  TDropOut = record
    Start: cardinal;
    Size: cardinal;
  end;

  TDropArray = array of TDropOut;

procedure DropCopy(fsSource, fsTarget: TStream; drops: TDropArray);
var
  i: integer;
begin
  fsSource.Position := 0;
  fsTarget.Position := 0;
  for i := Low(drops) to High(drops) do
  begin
    fsTarget.CopyFrom(fsSource, drops[i].Start - fsSource.Position);
    fsSource.Seek(drops[i].Size, soFromCurrent);
  end;
  fsTarget.CopyFrom(fsSource, fsSource.Size - fsSource.Position);
end;
Die auszulassenden Bereiche werden im DropArray übermittelt und die Dateien werden über FileStreams angesprochen. Safety code ist nicht an Bord.

Grüße vom marabu

Schwedenbitter 5. Nov 2005 22:08

Re: Datei teilweise kopieren
 
@marabu: Danke für den Tip. Ich verstehe den Vorschlag aber so, dass ich mit Streams arbeiten muss. Das habe ich aber noch nie getan und habe dementsprechend wenig Ahnung davon. Falls ich mein Programm nochmal überarbeite, werde ich es aber mal versuchen.

Ansonsten habe ich hier einen Link zum Programm eingefügt. In Anbetracht des Umstandes, dass man mp3-Dateien nicht regelmäßig von teilweise lästigen TAGs löscht, habe ich mich mittlerweile mit den rund 30 Sek., die bei mir für eine 5,5 MB Datei benötigt werden, abgefunden.
Falls jemand das ganze verbessern will, stelle ich den Quelltext, unter der Bedingung, dass das Endergebnis Freeware bleibt, gern zur Verfügung.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:46 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