![]() |
TZipFile
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. |
AW: TZipFile
Hallo,
wenn du uns nicht sagst, was du dir ausgedacht hast, können wir's auch nicht beurteilen/verbessern. ;-) Grüße TurboMagic |
AW: TZipFile
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. |
AW: TZipFile
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;
|
AW: TZipFile
Zitat:
![]() |
AW: TZipFile
Hallo, ich habe es selbst noch nicht ausprobiert aber bin auf diesen code gestossen, vielleicht funktioniert es für nicht-Delphi-11?
![]()
Delphi-Quellcode:
Aufruf:
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;
Delphi-Quellcode:
Viel Erfolg!
ZipFile.Delete('document.txt');
ZipFile.Add(SS, 'document.txt'); |
AW: TZipFile
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. |
AW: TZipFile
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:
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:
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;
Delphi-Quellcode:
Machen nich die Ganzen Zip-Dinger auch eine Validierung? Geht das wenn die Datei schon gelöscht ist?
for i := Low(List) to High(List) do begin
Add(List[i]); TFile.Delete(List[i]); end; |
AW: TZipFile
Zitat:
Zitat:
|
AW: TZipFile
Hallo,
ich hab' den Fehler gefunden!
Delphi-Quellcode:
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.
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;
Delphi-Quellcode:
So ist es richtig.
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; 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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:32 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-2025 by Thomas Breitkreuz