![]() |
Re: 7-zip Entpacker einbinden
Zitat:
Zum Packen ruf ich die Methode IOutArchive.UpdateItems auf welche folgendermaßen ausschaut:
Delphi-Quellcode:
Es werden also zwei Interfaces erwartet - die Implementierung dieser Interfaces muss man selbst zur Verfügung stellen! Der outStream wird zum schreiben des Archivs benötigt, ich hab daher folgendes gemacht:
function UpdateItems(outStream: ISequentialOutStream; numItems: DWord; updateCallback: IArchiveUpdateCallback): HRESULT; stdcall;
Delphi-Quellcode:
Nachdem TStreamWriter das ISequentialOutStream Interface implementiert, kann eine TStreamWriter-Instanz als ISequentialOutStream verwendet werden (Delphi führt eine implizite Typumwandlung durch). Wenn die DLL jetzt Daten in das Archiv schreiben muss, so wird die Write-Methode des ISequentialOutStream Interfaces aufgerufen. Die Implementierung dieser Methode schaut bei mir so aus:
outStream := TStreamWriter.Create(TFileStream.Create(FParams.Filename, fmCreate)); // TStreamWriter ist der Wrapper für den TFileStream
FOutArchive.UpdateItems(outStream, FParams.Items.Count, callback);
Delphi-Quellcode:
TStreamWriter macht jetzt also nichts anderes als diese Write-Aufrufe an die Write-Methoden der internen TStream-Instanz weiter zu delegieren. In meinem Fall also an die TFileStream-Instanz die dem Constructor mitgegeben wurde, theroretisch kann man auch einen TMemoryStream, TBlobStream, ... verwenden (ob es sinnvoll ist ist zwar fraglich, es ist aber auf jeden Fall möglich).
function TStreamWriter.Write(const data: Pointer; Size: DWord; processedSize: PDWord): HRESULT;
var writeCount: Integer; begin try writeCount := FStream.Write(data^, Size); if Assigned(processedSize) then processedSize^ := writeCount; Result := S_OK; except Result := S_FALSE; end; end; Dasselbe gilt für das Callback-Interface - man muss eine eigene Implementierung dieses Interfaces zur Verfügung stellen, deren Methoden dann von der DLL aufgerufen werden. Den ganzen Ablauf im Detail zu erklären wäre jetzt zuviel, aber vielleicht hast du das Konzept jetzt verstanden und kannst dir den Rest alleine zusammensuchen. Gruß, Motzi |
Re: 7-zip Entpacker einbinden
|
Re: 7-zip Entpacker einbinden
Zitat:
So sieht meine Testroutine aus:
Delphi-Quellcode:
Erstmal ist komisch, warum der output eine Datei sein muss (ich entpacke DATEIEN oder einen ORDNER aber nicht immer EINE DATEI). Aber dann funktioniert "decoder.Code" nicht ganz. Als Input-Datei habe ich die Downloaddatei genommen.
procedure TForm1.Button1Click(Sender: TObject);
var outdir : string; var dictionary:integer; inStream:TBufferedFS; outStream:TBufferedFS; filesize:int64; i:integer; properties:array[0..4] of byte; decoder:TLZMADecoder; outSize:int64; v:byte; const propertiessize=5; begin if (OpenDialog1.Execute) and (SelectDirectory('Ort zum Entpacken wählen', '', outdir)) then begin if outdir[Length(outdir)] <> '\' then outdir := outdir + '\'; inStream:=TBufferedFS.Create(OpenDialog1.FileName,fmOpenRead or fmsharedenynone); outStream:=TBufferedFS.Create(outdir + 'bla', fmcreate); if inStream.read(properties, propertiesSize) <> propertiesSize then raise Exception.Create('input .lzma file is too short'); decoder := TLZMADecoder.Create; if not decoder.SetDecoderProperties(properties) then raise Exception.Create('Incorrect stream properties'); outSize := 0; for i := 0 to 7 do begin v := {shortint}(ReadByte(inStream)); if v < 0 then raise Exception.Create('Can''t read stream size'); outSize := outSize or v shl (8 * i); end; if not decoder.Code(inStream, outStream, outSize) then raise Exception.Create('Error in data stream'); decoder.Free; outStream.Free; inStream.Free; end; end; Woran es genau liegt weiß ich nicht, da ich die Code-Routine einfach nicht verstehe (aufgrund der wunderbaren Dokumentation). Auf jeden Fall erreicht er folgende Bedingung (weshalb er abbricht) (ungefähr Z. 382):
Delphi-Quellcode:
MfG
if (rep0 >= nowPos64) or (rep0 >= m_DictionarySizeCheck) then begin
m_OutWindow.Flush(); result:=false; exit; end; xZise |
Re: 7-zip Entpacker einbinden
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
ich habe versucht das Entpacken zu implementieren. Und ich kann sogar ohne Änderung das nicht kompilieren, weil: Zitat:
Ich habe das einfach mal in Unicode bzw Nativ geändert (also bei D2k9 Unicode davor Ansi). Nebenbei bin ich in der Implementation des Entpackers: Es gibt schon die Möglichkeit ein geöffnetes Archiv zu schließen und so gut wie auch die Möglichkeit ein Archiv zu öffnen. Leider gibt es einen Parameter mit dem ich nichts anfangen kann:
Delphi-Quellcode:
Aber ansonsten habe ich das System ein bisschen umgestellt. Und zwar gibt es von fast allen einmal eine Basisklasse (z.B. TArchiveBase) von denen der Entpacker (z.B. TInArchive) und Packer (z.B. TOutArchive) abgeleitet sind. Ich hoffe das dies so sauber implementiert ist.
FInArchive.Open(FStream, <HIERHIERHIER>, Callback);
function Open(stream: IInStream; const maxCheckStartPosition: PInt64; openArchiveCallback: IArchiveOpenCallback): HRESULT; stdcall; Ich habe mal eine Frage an dich, Motzi, und zwar warum hast du beim "TProgressEvent" den Fortschritt als DWord (also Integer) angibst, wenn es nur Werte zwischen 0 und 100 (= Byte ... eigentlich nur 7-Bit) gibt? [edit]Ich hatte leider die falsche Version hoch geladen. Mit dieser geht es aktuell noch nicht, da muss ich mir noch was überlegen![/edit] MfG xZise |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:47 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