Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Zip-Archiv entpacken (https://www.delphipraxis.net/203066-zip-archiv-entpacken.html)

Guido Eisenbeis 9. Jan 2020 14:32


Zip-Archiv entpacken
 
Hallo.

Ich suche eine einfache Möglichkeit, ein Zip-Archiv zu entpacken.

Nach Recherchieren im INet und im Forum habe ich alles verworfen. Das meiste ist uralt, anderes gibts nicht mehr, weil der Entwickler verstorben ist, manches ist kostenpflichig, und nochmal anderes ist mir zu aufwendig, oder ich kriege es nicht auf die Reihe.

Das bisher geeignetste ist System.Zip.TZipFile.ExtractZipFile. Es ist in Delphi 10.3 schon enthalten und macht nur das eine, was ich brauche: Es entpackt eine Zip-Datei in einen Ziel-Ordner. Was ich bisher habe:

Delphi-Quellcode:
type
  TForm1 = class(TForm)
  ...
  private
    { Private-Deklarationen }
    class procedure ShowZipProgress(Sender: TObject; FileName: string;
      Header: TZipHeader; Position: Int64);
Delphi-Quellcode:
implementation

{$R *.dfm}

class procedure TForm1.ShowZipProgress(Sender: TObject; FileName: string;
  Header: TZipHeader; Position: Int64);
begin
  // Show your progress here, whatever it needs to do

  ProgressBar1.Max := Header.UncompressedSize; // <== Edit - hatte ich vergessen.
  ProgressBar1.Position := Position;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ProgressBar1.Max := 0;
  TZipFile.ExtractZipFile('F:\1\Test.zip', 'F:\1\2\', ShowZipProgress);
end;
Was unbedingt fehlt sind eine Möglichkeit das Ende des Entpack-Vorgangs zu erkennen, und eine Möglichkeit zum Abbrechen des Entpackvorgangs (z. B. weil es zu lange dauert).

Was dazu könnte, wäre eine Progressanzeige. Das ProgressBar1.Position := Position; das ich verwende, funktioniert hierbei nicht. Es wird kein Gesamtfortschritt gezeigt, sondern für jede Datei einzeln. Die Progressbar flackert also ständig.

Wichtig sind allerdings die beiden Punkte "Entpacken-Ende erkennen" und "Entpacken abbrechen". Hat jemand ein Code-Beispiel?


Edit: Hinweis gefunden und oben eingefügt, dass vor die Event-Deklaration ein "class" gehört: class procedure ShowZipProgress(Sender: ...

KodeZwerg 9. Jan 2020 14:45

AW: Zip-Archiv entpacken
 
sorry, war falsch

hoika 9. Jan 2020 15:01

AW: Zip-Archiv entpacken
 
Hallo,
hm

sowas wie das hier ?

You can get the progress of the current operation like this:
PercentageOfCompletion := Position div Header.UncompressedSize;

(http://docwiki.embarcadero.com/Libra...pProgressEvent)

Und das Flackern kannst du doch selber beinflussen,
Delphi-Quellcode:
if PercentageOfCompletion mod 5 = then
begin
  Position:= PercentageOfCompletion;
end;
Dann wird alle 5% Entpackfortschritt der Balken weitergesetzt.
Da Du ja nur eine Datei entpackst, sollte das ja reichen.


Zitat:

Was unbedingt fehlt sind eine Möglichkeit das Ende des Entpack-Vorgangs zu erkennen
TZipFile.ExtractZipFile('F:\1\Test.zip', ['F:\1\2\', ShowZipProgress);
-> Ende des Entpackens ...


PS:
es gibt noch TZipMaster (benutze ich) und Abbrevia.

Incocnito 9. Jan 2020 15:05

AW: Zip-Archiv entpacken
 
Ohne groß zu probieren, vielleicht ist es ja tatsächlich so einfach:
Zitat:

Zitat von Guido Eisenbeis (Beitrag 1454768)
...
Delphi-Quellcode:
...
procedure TForm1.ShowZipProgress(Sender: TObject; FileName: string;
  Header: TZipHeader; Position: Int64);
begin
  // Show your progress here, whatever it needs to do

  if (ProgressBar1.Max = 0) then ProgressBar1.Max := Header.UncompressedSize;

  ProgressBar1.Position := Position;
end;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
  ProgressBar1.Max := 0;
  TZipFile.ExtractZipFile('F:\1\Test.zip', 'F:\1\2\', ShowZipProgress);
  ShowMessage('Fertig!');// <- Ist der hier nicht fertig?
end;
...

Liebe Grüße
Incocnito

Luckie 9. Jan 2020 15:23

AW: Zip-Archiv entpacken
 
Delphi-Quellcode:
procedure TForm16.OnZipProgressEvent(Sender: TObject; FileName: string;
  Header: TZipHeader; Position: Int64);
begin
  if PreviousFilename <> FileName then
  begin
    StaticText1.Caption := ExtractFileName(FileName);
    PreviousFilename := FileName;
    ProgressBar1.Position := 0;
  end
  else
    ProgressBar1.Position := (Position * 100) div Header.UncompressedSize ;
  Application.ProcessMessages;
end;
Gefunden in 10 Sekunden mit Google mit "ShowZipProgress delphi". Mit etwas mehr Eigeninitiative hättest du dein Problem selbst innerhalb kurzer Zeit lösen können. :roll:

Btw. da Befehle nacheinander abgearbeitet werden, ist das Entpacken beendet, wenn
Delphi-Quellcode:
TZipFile.ExtractZipFile('F:\1\Test.zip', 'F:\1\2\', ShowZipProgress);
ausgeführt wurde. Also da nach. Es ist also eindeutig klar, wann das Entpacken fertig ist.

Guido Eisenbeis 9. Jan 2020 16:07

AW: Zip-Archiv entpacken
 
Zitat:

Zitat von Luckie (Beitrag 1454777)
Mit etwas mehr Eigeninitiative hättest du dein Problem selbst innerhalb kurzer Zeit lösen können. :roll:

Würdest du das bitte unterlassen? Das ist nicht hilfreich und du weißt doch gar nicht, wieviel Eigeninitiative ich schon reingesteckt habe!

Zitat:

Zitat von Luckie (Beitrag 1454777)
Gefunden in 10 Sekunden mit Google mit "ShowZipProgress delphi".

Mehr ist es auch nicht wert, denn es funktioniert nicht! Zudem finde ich es auch herablassend, wie du mit mir sprichst. Irgendwer hat dir wohl weh getan, dass du so zornig bist. Aber ich war das nicht!

Zitat:

Zitat von hoika (Beitrag 1454772)
TZipFile.ExtractZipFile('F:\1\Test.zip', ['F:\1\2\', ShowZipProgress);
-> Ende des Entpackens ...

Zitat:

Zitat von Incocnito (Beitrag 1454773)
Ohne groß zu probieren, vielleicht ist es ja tatsächlich so einfach:
Delphi-Quellcode:
  TZipFile.ExtractZipFile('F:\1\Test.zip', 'F:\1\2\', ShowZipProgress);
  ShowMessage('Fertig!');// <- Ist der hier nicht fertig?

Zitat:

Zitat von Luckie (Beitrag 1454777)
Btw. da Befehle nacheinander abgearbeitet werden, ist das Entpacken beendet, wenn
Delphi-Quellcode:
TZipFile.ExtractZipFile('F:\1\Test.zip', 'F:\1\2\', ShowZipProgress);
ausgeführt wurde. Also da nach. Es ist also eindeutig klar, wann das Entpacken fertig ist.

Da war ich wohl blind, denn ihr habt alle Recht! 1 Problem gelöst! Vielen Dank! :-D

Guido Eisenbeis 9. Jan 2020 16:24

AW: Zip-Archiv entpacken
 
Zitat:

Zitat von Guido Eisenbeis (Beitrag 1454768)
Was dazu könnte, wäre eine Progressanzeige. Das ProgressBar1.Position := Position; das ich verwende, funktioniert hierbei nicht. Es wird kein Gesamtfortschritt gezeigt, sondern für jede Datei einzeln. Die Progressbar flackert also ständig.

Folgende Infos zum Flackern der Progressanzeige:

Das Flackern kommt nicht von einem visuellen Darstellungs-Problem, sondern dadurch dass es für jede einzelne Datei ganz vorne anfängt und bis zum Ende der Progressbar läuft, dann fängt die nächste Datei wieder vorne an, und läuft bis ans Ende. Wenn ein Zip-Archiv z. B. 7.400 Dateien enthält, dann passiert das 7.400 mal ==> also flackerts. :wink:

venice2 9. Jan 2020 16:44

AW: Zip-Archiv entpacken
 
Zitat:

7.400 Dateien enthält, dann passiert das 7.400 mal ==> also flackerts.
Eigentlich dürfte das kein Problem sein wenn du die Menge an Dateien im Archiv vorher ermitteln kannst.
Richte deine Progress-bar Max dementsprechend aus.
Es zwingt dich dann niemand immer wieder von vorne zu beginnen.

hoika 9. Jan 2020 16:55

AW: Zip-Archiv entpacken
 
Hallo,
ich kenne TZipFile ja nicht, aber

Bekommst Du die Anzahl der Dateien raus ?
Dann kannst Du ja Gesamt-Dateigrößen über
property FileInfo[Index: Integer]: TZipHeader
ermitteln.

Ich habe aber keine FileCount gefunden, muss es aber doch geben, oder ?

Danach kannst Du im ProgressEvent ja dann komplett hochzählen lassen,
also eine eigene Variable, die mit Hilfe von Position hochzählt.

PS:
laut dem hier gibt es FileCount
http://delphiblog.twodesk.com/native...-in-delphi-xe2
property FileCount: Integer; //total number of files in the zip file

Luckie 9. Jan 2020 16:57

AW: Zip-Archiv entpacken
 
Woher soll ich wissen, was du schon probiert hast oder nicht?

Hättest du geschrieben: "Hier habe ich den und den Quellcode gefunden. Der funktioniert aber bei mir nicht. Es kommt die und die Fehlermeldung beim Kompilieren/Ausführen", dann hätte man zum einem gesehen, dass du dich schon selbst um das Problem gekümmert hast, das kommt immer gut an, und man hätte eine Grundlage für die weitere Hilfe gehabt.

So hast du uns zwei Codeschnippsel gegeben und gesagt "ich will". Das hat bei mir etwas Unmut ausgelöst. Entschuldige bitte.

Es flackert nicht, die Fortschrittsanzeige fängt nur für jede Datei von vorne an. Du willst aber anscheinend den Gesamtfortschritt. Dazu musst du die Endgröße ermitteln und den jeweiligen Einzelfortschritt merken und aufsummieren. Also noch etwas drumrum basteln. Es wird also vorher erforderlich sein vorher in einer Schleife die Größe aller Dateien zusammen zu ermitteln.

venice2 9. Jan 2020 17:32

AW: Zip-Archiv entpacken
 
Nun denn!

Delphi-Quellcode:
var
  zipFile: TZipFile;
  fileCount: Integer;
  filename: string;
begin
  zipFile := TZipFile.Create;
  filename := 'xxx'
  zipFile.Open(filename, zmRead);
  fileCount := zipFile.FileCount;
end;

Guido Eisenbeis 10. Jan 2020 03:26

AW: Zip-Archiv entpacken
 
Zitat:

Zitat von Luckie (Beitrag 1454787)
So hast du uns zwei Codeschnippsel gegeben und gesagt "ich will". Das hat bei mir etwas Unmut ausgelöst. Entschuldige bitte.

Vielen Dank! :-D

Wir "kennen" uns schon seit über 10 Jahren, bei mir kannst du davon ausgehen, dass ich mich vor dem Posten intensiv bemüht habe, Lösungen selbst zu finden. :wink:


Zurück zum Thema "Entpacken eines Zip-Archivs"

Dank eurer Hilfe habe ich nun eine Lösung zusammengestellt, mit der ein Zip-Archiv in einen Zielordner entpackt werden kann. Dabei ist eine Fortschrittsanzeige möglich und das Ende des Vorgangs kann festgestellt werden. Und das alles ohne zusätzliche Komponenten, nur mit Delphi internen Möglichkeiten! :thumb:

Besonderer Dank geht an hoika! Dein Link hat mir den Anfang ermöglicht. Native Zip file support in Delphi XE2 Damit hatte ich Informationen zum Erstellen eines TZipFile-Objekts, und mit den Anweisungen im try-finally Block konnte ich sehen, wie und was wieder freigegeben werden muss. :thumb:

Information am Rande: zipFile.FileCount gibt einen höheren Wert aus, als ein Datei-Zähler beim Auspacken des Zip-Archivs. Das wird im Moment zwar nicht benötigt, aber interessant wäre es, warum das so ist. Meine Vermutung ist, dass zipFile.FileCount die Ordner im Zip-Archiv mitzählt.

Somit sind 2 von 3 Problemen gelöst. Fehlt nur noch die Möglichkeit zum Abbrechen eines laufenden Entpack-Vorganges. Ideen? :idea:

Luckie 10. Jan 2020 04:20

AW: Zip-Archiv entpacken
 
Und wie sieht dein Code jetzt aus?

Abbrechen müsste in dem Fortschrittsereignis möglich sein.

PS: Wir kennen uns seit 10 Jahren? :shock: Hattest du mal einen anderen Benutzernamen?

Guido Eisenbeis 10. Jan 2020 04:49

AW: Zip-Archiv entpacken
 
Zitat:

Zitat von Luckie (Beitrag 1454823)
Und wie sieht dein Code jetzt aus?

Ziemlich durcheinander. Ich räume gerade darin auf. Wenn es jemand interessiert, kann ich das Ergebnis gerne posten.

Zitat:

Zitat von Luckie (Beitrag 1454823)
Abbrechen müsste in dem Fortschrittsereignis möglich sein.

Das scheint mir der richtige Platz zu sein, aber wie kann man das bewerkstelligen? :gruebel:

Zitat:

Zitat von Luckie (Beitrag 1454823)
PS: Wir kennen uns seit 10 Jahren? :shock: Hattest du mal einen anderen Benutzernamen?

Damals nicht. :) "Kennen" in Anführungszeichen meint, dass du eine schillernde Person der Öffentlichkeit warst / bist (= VIP) und ich in jedem zweiten Code-Snippet deinen Namen gefunden habe. Ich selbst bin wohl so unbedeutend, dass du dich nicht erinnern kannst. :cry:

Luckie 10. Jan 2020 07:21

AW: Zip-Archiv entpacken
 
Hat die Klasse eine Eigenschaft zum Abbrechen? Dann einfach im Progress-Eventhandler:
Delphi-Quellcode:
if bAbort then zipFile.Abort
Oder wie auch immer die Eigenschaft heißt.

hoika 10. Jan 2020 07:32

AW: Zip-Archiv entpacken
 
Hallo,
im ProgressEvent einfach eine Exception erzeugen?

Delphi-Quellcode:
procedure TForm1.OnZipProgress();
begin
  Application.ProcessMe3ssages; // wichtig

  if bAbort then
  begin
    Exception.Create('');
  end;
end;


// Button "Abbrechen"-Klick Methode
procedure TForm1.OnBtnCancelClick;
begin
  bAbort:= True;
end;

procedure TForm1.Entpacke;
begin
  ...
  try
    Zipfile.Extract ...
  except
  end;
end;

Guido Eisenbeis 10. Jan 2020 07:43

AW: Zip-Archiv entpacken
 
Zitat:

Zitat von Luckie (Beitrag 1454837)
Hat die Klasse eine Eigenschaft zum Abbrechen? Dann einfach im Progress-Eventhandler:
Delphi-Quellcode:
if bAbort then zipFile.Abort

Ich habe den Thread erstellt, um ebendiese Information zu bekommen. Weiß jemand, wie man das macht? Gesucht habe ich danach in der Klasse TZipFile, TZipFile.FileInfo und TZipHeader. Leider erfolglos, ein Abort habe ich nicht gefunden. Es gibt ein Close, aber ob das so gut ist, mittendrin einfach zu schließen!? Zudem steht zu der Pozedur in der Hilfe: Dateien können aus einem Archiv ohne Instantiierung von TZipFile-Objekten mit der Klassenprozedur ExtractZipFile extrahiert werden.

Hat jemand eine Idee?

Incocnito 10. Jan 2020 14:45

AW: Zip-Archiv entpacken
 
Ein kurzer Blick in System.zip ...
ExtractZipFile ist übersichtlich, das "magische" passiert wiederum in "extractall" ...
Auch diese ist übersichtlich und beinhaltet eine Schleife über alle Dateien.
Hier fehlt schon die Option zum Abbrechen ...
Im Wesentlichen ruft "ExtractAll" also "Extract" in einer Schleife auf.
Hier wird dann die komplette Datei "in einem Rutsch" in einen Stream geladen,
danach beschäftigt sich die Funktion im Wesentlichen darum die passende Datei (TFileStream)
anzulegen. Anschließend wird "OnProgress" aufgerufen. Da ist das aber alles schon vorbei.
Ich würde sagen, mit "Syste.Zip.TZipFile.ExtractZipFile" ist ein Abbrechen nicht möglich.

Nächster Versuch wäre "System.ZLib", aber die ist etwas größer als dass ich da eine Aussage treffen würde.
Spontan habe ich nichts mit Abbrechen-Funktion gefunden, aber wie gesagt, sicher kann ich das nicht sagen.

Liebe Grüße
Incocnito

Guido Eisenbeis 12. Jan 2020 15:27

AW: Zip-Archiv entpacken
 
Zitat:

Zitat von hoika (Beitrag 1454838)
im ProgressEvent einfach eine Exception erzeugen?[/DELPHI]

Interessanter Gedanke. Mit welchen Auswirkungen ist denn im schlimmsten Fall zu rechnen?

Zitat:

Zitat von Incocnito (Beitrag 1454873)
Im Wesentlichen ruft "ExtractAll" also "Extract" in einer Schleife auf.
...
Ich würde sagen, mit "Syste.Zip.TZipFile.ExtractZipFile" ist ein Abbrechen nicht möglich.

Sieht so aus. Danke für eure Antworten!

zeras 12. Jan 2020 15:51

AW: Zip-Archiv entpacken
 
Da wir schon beim Entzippen sind. Kann das nun integrierte Zippen/Entzippen auch in einen Stream entzippen?
Ich habe noch Delphizip im Einsatz. Dort steht aber, das die aus Gesundheitsgründen nicht mehr weiterentwicklelt wird.
Daher suche ich nach einer Alternative in Zukunft. Wenn das schon in Delphi integriert ist, wäre das meines Erachtens die beste Alternative.

scrat1979 12. Jan 2020 16:02

AW: Zip-Archiv entpacken
 
Zitat:

Zitat von zeras (Beitrag 1454997)
Da wir schon beim Entzippen sind. Kann das nun integrierte Zippen/Entzippen auch in einen Stream entzippen?
Ich habe noch Delphizip im Einsatz. Dort steht aber, das die aus Gesundheitsgründen nicht mehr weiterentwicklelt wird.
Daher suche ich nach einer Alternative in Zukunft. Wenn das schon in Delphi integriert ist, wäre das meines Erachtens die beste Alternative.

Mit TZipForge von ComponentAce geht das auf jeden Fall. Eventuell wäre dies noch einen Blick wert. Für den kommerziellen Einsatz zwar nicht kostenlos, aber durchaus preislich im Rahmen. Verwende ich in einigen Projekten und bin top zufrieden.

philipp.hofmann 12. Jan 2020 16:54

AW: Zip-Archiv entpacken
 
Ich benutze auch TZipForge, weil es auch sehr große Zip-Dateien unterstützt, wo TZipFile aussteigt und dies benötige ich in einigen Projekten.

Guido Eisenbeis 12. Jan 2020 16:58

AW: Zip-Archiv entpacken
 
Zitat:

Zitat von zeras (Beitrag 1454997)
Da wir schon beim Entzippen sind. Kann das nun integrierte Zippen/Entzippen auch in einen Stream entzippen?

Das scheint möglich. Native Zip file support in Delphi XE2

Uwe Raabe 12. Jan 2020 22:50

AW: Zip-Archiv entpacken
 
Zitat:

Zitat von Guido Eisenbeis (Beitrag 1454840)
Hat jemand eine Idee?

Einfach im OnProgress-Event
Delphi-Quellcode:
Abort
(aus System.SysUtils) aufrufen. Das erzeugt intern auch eine Exception, aber genau diese wird sowohl von der IDE als auch von der TApplication ignoriert. Man bricht also einfach die aktuelle Aufgabe ab (daher wohl auch der Name).

Zitat:

Zitat von Incocnito (Beitrag 1454873)
Hier wird dann die komplette Datei "in einem Rutsch" in einen Stream geladen,
danach beschäftigt sich die Funktion im Wesentlichen darum die passende Datei (TFileStream)
anzulegen. Anschließend wird "OnProgress" aufgerufen. Da ist das aber alles schon vorbei.

Das OnProgress wird aber auch noch innerhalb dieses "Rutsch" aufgerufen. Insofern kann man auch während des Extract einer Datei abbrechen.

Guido Eisenbeis 12. Jan 2020 23:15

AW: Zip-Archiv entpacken
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1455031)
Einfach im OnProgress-Event
Delphi-Quellcode:
Abort
(aus System.SysUtils) aufrufen.

Ich habe es kurz ausprobiert. Es bricht zwar die Ausführung ab, aber die Anwendung ist nicht mehr ansprechbar.

Im OnProgress-Event habe ich eingefügt
Delphi-Quellcode:
if g_bAbort then Abort;
In der Hilfe steht "Abort übergibt die Ausführung an das Ende des letzten Exception-Blocks." Kannst du mir bitte das Drumrum zeigen? Muss da ein Try-Exept Konstrukt hin? Wo mache ich meine anderen Code im OnProgress-Event hin?

Incocnito 13. Jan 2020 07:38

AW: Zip-Archiv entpacken
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1455031)
Zitat:

Zitat von Incocnito (Beitrag 1454873)
Hier wird dann die komplette Datei "in einem Rutsch" in einen Stream geladen,
danach beschäftigt sich die Funktion im Wesentlichen darum die passende Datei (TFileStream)
anzulegen. Anschließend wird "OnProgress" aufgerufen. Da ist das aber alles schon vorbei.

Das OnProgress wird aber auch noch innerhalb dieses "Rutsch" aufgerufen. Insofern kann man auch während des Extract einer Datei abbrechen.

Am Ende von Read wird das OnProgress übergeben ... habe ich in der Tat übersehen!
Sehr gut aufgepasst! :thumb:


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