AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

TZipFile

Ein Thema von Willie1 · begonnen am 3. Dez 2021 · letzter Beitrag vom 9. Dez 2021
Antwort Antwort
Seite 1 von 2  1 2      
Willie1

Registriert seit: 28. Mai 2008
655 Beiträge
 
Delphi 10.1 Berlin Starter
 
#1

TZipFile

  Alt 3. Dez 2021, 18:19
Hallo, jetzt zu meiner Frage.
Ich packe ca. 80 Dateien jede 2939 oder2777 Bytes groß in ein Zip-Archiv. Nicht um Platz zu sparen, sondern mit nur einer Datei umgehen zu können. Ich benutze TZipFile. Das auspacken klappt, mit dem Packen gibt es ein Problem. Mit TZipFile.Add lässt sich keine Datei im Archiv überschreiben. (Habe ich hier gelernt) Deshalb habe ich mir selbst was ausgedacht, wahrscheinlich umständlich aber ich kann es nicht besser. Das funktioniert auch und das Archiv lässt sich mit TZipFile wieder auspacken auch mit dem Windows-Explorer und WinRar. Nur ist mir erst jetzt nach 6 Mon. aufgefallen, dass mein Zip riesig groß wird, größer als das Original. Was ist da los?
Quellcode kann ich hochladen.
Willie

Nebenbei: Das Szenario von gestern wiederholt sich. Wenn ich Vorschau anklicke, muss ich mich wieder anmelden Diesmal hat die Rückwärtstaste geholfen. Die Vorschau geht nicht.
Gut hören kann ich schlecht, schlecht sehen kann ich gut - Ersteres stimmt nicht, das zweite schon.

Geändert von Willie1 ( 3. Dez 2021 um 18:21 Uhr)
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.938 Beiträge
 
Delphi 12 Athens
 
#2

AW: TZipFile

  Alt 3. Dez 2021, 18:53
Hallo,

wenn du uns nicht sagst, was du dir ausgedacht hast, können wir's auch nicht beurteilen/verbessern.

Grüße
TurboMagic
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: TZipFile

  Alt 3. Dez 2021, 21:50
Die etwas Delphi-Implementation kann nur anhängen, aber nichts nachträglich ändern/überschreiben/löschen.

Du müsstest also die Datei kopieren, also lesend von einer ZIP, schreibend in eine Neue, und beim Kopieren deine Änderungen vornehmen.



Wenn die Dateigröße egal ist, dann einfach die Datei nochmal anhängen (mit dem gleichen Dateinamen) und beim entpacken überschreiben lassen, bzw. jeweils die letzte Version auslesen.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu ( 3. Dez 2021 um 21:59 Uhr)
  Mit Zitat antworten Zitat
Willie1

Registriert seit: 28. Mai 2008
655 Beiträge
 
Delphi 10.1 Berlin Starter
 
#4

AW: TZipFile

  Alt 4. Dez 2021, 11:45
Delphi-Quellcode:
procedure TWZZipFile.AddandOverride(const aFilename: string; const ArchiveFileName: string);
var
  TempPa, TempName: string;
  List: TStringDynArray;
  i: Integer;
  Done: Boolean;
begin
  if TFileAttribute.faReadOnly in TFile.GetAttributes(ArchiveFilename, false) then begin
    ShowMessage('Archiv "'+ExtractFilename(ArchiveFilename)+'"ist schreibgeschützt!');
    Exit;
  end;
  Done := false;
  if IsValid(ArchiveFilename) then begin
// TempPa := TPath.GetTempPath+Format('~~~%.4x',[Random($FFFF)]);
    TempPa := TPath.Combine(TPath.GetTempPath, TPath.GetRandomFileName);
    TDirectory.CreateDirectory(TempPa);
    Open(ArchiveFilename, zmRead);
    ExtractAll(TempPa);
    if CopyFile(PWideChar(aFilename), PWideChar(TPath.Combine(TempPa, ExtractFilename(aFilename))), false) then
    begin
      List := TDirectory.GetFiles(TempPa);
      TempName := ExtractFilePath(ArchiveFilename) + ExtractFilename(TPath.GetTempFileName);
      Open(TempName, zmWrite);
      for i := Low(List) to High(List) do begin
        Add(List[i]);
        TFile.Delete(List[i]);
      end;
      Close;
      Done := true;
    end;
    Close;
  end;
  if Done then begin
    TFile.Delete(ArchiveFilename);
    if RenameFile(TempName, ArchiveFilename) then
      TDirectory.Delete(TempPa, true);
  end;
end;

procedure TWZZipFile.AddandOverride(const aFileNames: TStrings; const ArchiveFileName: string);
var
  TempPa, TempName: string;
  List: TStringDynArray;
  i: Integer;
  Done: Boolean;
begin
  if TFileAttribute.faReadOnly in TFile.GetAttributes(ArchiveFilename, false) then begin
    ShowMessage('Archiv "'+ExtractFilename(ArchiveFilename)+'"ist schreibgeschützt!');
    Exit;
  end;
  Done := false;
  if IsValid(ArchiveFilename) then begin
    TempPa := TPath.Combine(TPath.GetTempPath, TPath.GetRandomFileName);
    TDirectory.CreateDirectory(TempPa);
    Open(ArchiveFilename, zmRead);
    ExtractAll(TempPa);
    for i := 0 to aFilenames.Count - 1 do begin
      Done := CopyFile(PWideChar(aFilenames[i]), PWideChar(TPath.Combine(TempPa, ExtractFilename(aFilenames[i]))), false);
      if not Done then Break;
    end;
    if Done then begin
      Done := false;
      List := TDirectory.GetFiles(TempPa);
      TempName := ExtractFilePath(ArchiveFilename) + ExtractFilename(TPath.GetTempFileName);
      Open(TempName, zmWrite);
      for i := Low(List) to High(List) do begin
        Add(List[i]);
        TFile.Delete(List[i]);
      end;
      Close;
      Done := true;
    end;
    Close;
  end;
  if Done then begin
    TFile.Delete(ArchiveFilename);
    if RenameFile(TempName, ArchiveFilename) then
      TDirectory.Delete(TempPa, true);
  end;
end;
  1. Archiv in Temp-Ordner auspacken
  2. Datei(en) dort hinein kopieren und eventuell überschreiben
  3. Neues Archiv mit Add anlegen
  4. Altes Archiv löschen und neues umbebenenn.
So habe ich es mir vorgegetellt. Willie.
Gut hören kann ich schlecht, schlecht sehen kann ich gut - Ersteres stimmt nicht, das zweite schon.

Geändert von Willie1 ( 4. Dez 2021 um 11:47 Uhr) Grund: Ach ja, die Rechtschreibung
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.530 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: TZipFile

  Alt 4. Dez 2021, 12:35
Die etwas Delphi-Implementation kann nur anhängen, aber nichts nachträglich ändern/überschreiben/löschen.

Du müsstest also die Datei kopieren, also lesend von einer ZIP, schreibend in eine Neue, und beim Kopieren deine Änderungen vornehmen.



Wenn die Dateigröße egal ist, dann einfach die Datei nochmal anhängen (mit dem gleichen Dateinamen) und beim entpacken überschreiben lassen, bzw. jeweils die letzte Version auslesen.
Ich hab es selber noch nicht ausprobiert, aber Delphi 11 soll nun auch Dateien aus dem Archiv entfernen können (delete):

https://docwiki.embarcadero.com/Libr...ZipFile.Delete
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: TZipFile

  Alt 5. Dez 2021, 00:09
Hallo, ich habe es selbst noch nicht ausprobiert aber bin auf diesen code gestossen, vielleicht funktioniert es für nicht-Delphi-11?
stackoverflow.com
Delphi-Quellcode:
type
  TZipFileHelper = class helper for TZipFile
    procedure Delete(FileName: string);
  end;

{ TZipFileHelper }

procedure TZipFileHelper.Delete(FileName: string);
var
  i, j: Integer;
  StartOffset, EndOffset, Size: UInt32;
  Header: TZipHeader;
  Buf: TBytes;
begin
  i := IndexOf(FileName);
  if i <> -1 then begin
    // Find extents for existing file in the file stream
    StartOffset := Self.FFiles[i].LocalHeaderOffset;
    EndOffset := Self.FEndFileData;
    for j := 0 to Self.FFiles.Count - 1 do begin
      if (Self.FFiles[j].LocalHeaderOffset > StartOffset) and
         (Self.FFiles[j].LocalHeaderOffset <= EndOffset) then
        EndOffset := Self.FFiles[j].LocalHeaderOffset;
    end;
    Size := EndOffset - StartOffset;
    // Update central directory header data
    Self.FFiles.Delete(i);
    for j := 0 to Self.FFiles.Count - 1 do begin
      Header := Self.FFiles[j];
      if Header.LocalHeaderOffset > StartOffset then begin
        Header.LocalHeaderOffset := Header.LocalHeaderOffset - Size;
        Self.FFiles[j] := Header;
      end;
    end;
    // Remove existing file stream
    SetLength(Buf, Self.FEndFileData - EndOffset);
    Self.FStream.Position := EndOffset;
    if Length(Buf) > 0 then
      Self.FStream.Read(Buf[0], Length(Buf));
    Self.FStream.Size := StartOffset;
    if Length(Buf) > 0 then
      Self.FStream.Write(Buf[0], Length(Buf));
    Self.FEndFileData := Self.FStream.Position;
  end;
end;
Aufruf:
Delphi-Quellcode:
ZipFile.Delete('document.txt');
ZipFile.Add(SS, 'document.txt');
Viel Erfolg!
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Willie1

Registriert seit: 28. Mai 2008
655 Beiträge
 
Delphi 10.1 Berlin Starter
 
#7

AW: TZipFile

  Alt 5. Dez 2021, 18:25
Hallo KodeZwerg,
da hast du was Gutes bei Overflow gefunden. Ich werde es testen, bin aber sicher, dass es geht. Da habe ich schon oft Gutes gefunden.
Ich habe nur ein Problem: Bei dieser Methode wird wohl nur der Header gelöscht, die Datei bleibt. Mein von mir gegangener Weg wird bei Overflow genau so erwähnt. Bei 80 Dateien geht das sehr schnell und Speicherplatz auf der Festplatte ist kein Thema mehr.
Mein Ansatz ist richtig, könnt ihr erkennen, was an meinem Quelltext falsch ist. Sorry für meine Hartnäckigkeit.
Ich werde ein Archiv mit 80 Dateien mit dem Windows-Explorer packen und dann mit TZipFile und die Größe vergleichen.
Getan: Mit Windows: 87 KB mit TZipFile.Add: 90 KB. 75 Dateien mit jeweils 2777/2939 Bytes.

Willie.
Gut hören kann ich schlecht, schlecht sehen kann ich gut - Ersteres stimmt nicht, das zweite schon.

Geändert von Willie1 ( 5. Dez 2021 um 19:31 Uhr) Grund: TZipFile getestet
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.736 Beiträge
 
Delphi 6 Enterprise
 
#8

AW: TZipFile

  Alt 7. Dez 2021, 10:39
Hat nichts mit deinem Problem zu tun, aber wenn du die Funktion für nur eine Datei so abänderst, musst du das Problem anschließend nur in einer Funtion beheben, hast also nicht so viel doppelten Code.

Delphi-Quellcode:
procedure TWZZipFile.AddandOverride(const aFilename: string; const ArchiveFileName: string);
var s:TStringlist;
begin
  s:=TStringlist.create;
  s.Add(aFilename);
  AddandOverride(s, ArchiveFileName);
  s.Free;
end;
Zum Problem: Ich hab noch nicht mit TZipFile gearbeitet, aber kann das hinzufügen zum Archiv und direkt danach das löschen in einem Zug vielleicht das Problem sein:
Delphi-Quellcode:
  for i := Low(List) to High(List) do begin
        Add(List[i]);
        TFile.Delete(List[i]);
      end;
Machen nich die Ganzen Zip-Dinger auch eine Validierung? Geht das wenn die Datei schon gelöscht ist?
Ralph
  Mit Zitat antworten Zitat
Willie1

Registriert seit: 28. Mai 2008
655 Beiträge
 
Delphi 10.1 Berlin Starter
 
#9

AW: TZipFile

  Alt 8. Dez 2021, 19:43
Hat nichts mit deinem Problem zu tun, aber wenn du die Funktion für nur eine Datei so abänderst, musst du das Problem anschließend nur in einer Funtion beheben, hast also nicht so viel doppelten Code.

Delphi-Quellcode:
procedure TWZZipFile.AddandOverride(const aFilename: string; const ArchiveFileName: string);
var s:TStringlist;
begin
  s:=TStringlist.create;
  s.Add(aFilename);
  AddandOverride(s, ArchiveFileName);
  s.Free;
end;
Du hast recht.
Zitat:
Zum Problem: Ich hab noch nicht mit TZipFile gearbeitet, aber kann das hinzufügen zum Archiv und direkt danach das löschen in einem Zug vielleicht das Problem sein:
Delphi-Quellcode:
  for i := Low(List) to High(List) do begin
        Add(List[i]);
        TFile.Delete(List[i]);
      end;
Machen nich die Ganzen Zip-Dinger auch eine Validierung? Geht das wenn die Datei schon gelöscht ist?
Die Zip-Datei wird neu geschrieben, sie wird nur immer größer. Wi.
Gut hören kann ich schlecht, schlecht sehen kann ich gut - Ersteres stimmt nicht, das zweite schon.
  Mit Zitat antworten Zitat
Willie1

Registriert seit: 28. Mai 2008
655 Beiträge
 
Delphi 10.1 Berlin Starter
 
#10

AW: TZipFile

  Alt 9. Dez 2021, 18:03
Hallo,
ich hab' den Fehler gefunden!
Delphi-Quellcode:
      Open(TempName, zmWrite); //hier liegt der Fehler
      for i := Low(List) to High(List) do begin
        Add(List[i]);// <-----------------
        TFile.Delete(List[i]);
      end;
      Close;
ich benutze die Instanz TZipFile zweimal, einmal zum Auspacken des alten Zip und einmal zum Schreiben des neuen Zip. Ich war davon aus gegangen, dass mit Open Close ausgelöst wird (so steht es in der Hilfe) und das alte Archiv geschlossen wird. Das ist aber nicht so. Die alten Dateien werden nicht mehr "verlinkt", stehen aber noch im neuen Archiv. Deshalb wird es immer größer. So ist es mir zunächst nicht aufgefallen, weil es funktioniert.
Delphi-Quellcode:
  if Done then begin
      ZipFi := TZipFile.Create;// <--- Neu
      List := TDirectory.GetFiles(TempPa);
      TempName := ExtractFilePath(ArchiveFilename) + ExtractFilename(TPath.GetTempFileName);
      ZipFi.Open(TempName, zmWrite);
      for i := Low(List) to High(List) do begin
        ZipFi.Add(List[i]);
        TFile.Delete(List[i]);
      end;
      ZipFi.Free;
    end;
So ist es richtig.
Es stellt sich mir die Frage: liegt das an meinen Programmierkünsten oder haben die "Delphi-Bauer" etwas übersehen?
Gruß Willie,

Hoffentlich seit ihr hier noch dabei.
Gut hören kann ich schlecht, schlecht sehen kann ich gut - Ersteres stimmt nicht, das zweite schon.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 12:26 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