AGB  ·  Datenschutz  ·  Impressum  







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

7-zip Entpacker einbinden

Ein Thema von xZise · begonnen am 15. Feb 2008 · letzter Beitrag vom 4. Aug 2009
Antwort Antwort
Seite 3 von 3     123   
Benutzerbild von Motzi
Motzi

Registriert seit: 6. Aug 2002
Ort: Wien
598 Beiträge
 
Delphi XE2 Professional
 
#21

Re: 7-zip Entpacker einbinden

  Alt 15. Mär 2008, 14:35
Zitat von xZise:
Ah okay. Ist etwas verwirrend Da muss man erstmal durchblicken
Was macht den genau TStreamReader?
TStreamReader implementiert die beiden Interfaces IInStrem und ISequentialInStream. Es muss ja irgendeine Schnittstelle geben über die dein Programm mit der DLL kommunizieren kann, und da nicht alle Programme in C++ geschrieben werden (so wie die DLL) muss diese Schnittstelle sprachenunabhängig sein - daher verwendet die DLL eben COM-Interfaces. Die ganze Kommunikation läuft folgendermaßen ab: du forderst ein Interface aus der DLL an (über die Funktion CreateObject, welche von der DLL exportiert wird). In meinem Fall (Packen) hab ich dazu eine IOutArchive-Instanz angefordert - du bräuchtest wohl eine IInArchive-Instanz. Ab dann läuft alles nur mehr über dieses Interface.
Zum Packen ruf ich die Methode IOutArchive.UpdateItems auf welche folgendermaßen ausschaut:
function UpdateItems(outStream: ISequentialOutStream; numItems: DWord; updateCallback: IArchiveUpdateCallback): HRESULT; stdcall; 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:
Delphi-Quellcode:
outStream := TStreamWriter.Create(TFileStream.Create(FParams.Filename, fmCreate)); // TStreamWriter ist der Wrapper für den TFileStream
FOutArchive.UpdateItems(outStream, FParams.Items.Count, callback);
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:
Delphi-Quellcode:
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;
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).
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
Manuel Pöter
  Mit Zitat antworten Zitat
MrKnogge

Registriert seit: 9. Jun 2003
Ort: Pforzheim
2.458 Beiträge
 
Delphi 2007 Professional
 
#22

Re: 7-zip Entpacker einbinden

  Alt 25. Mär 2008, 03:37
xZise hast du dir das hier schon mal angeschaut ?

Grüße
Christian
Christian Bootz
Einstein ist tot, Newton ist tot,
und mir ist auch schon ganz schlecht...
  Mit Zitat antworten Zitat
Benutzerbild von xZise
xZise

Registriert seit: 3. Mär 2006
Ort: Waldbronn
4.303 Beiträge
 
Delphi 2009 Professional
 
#23

Re: 7-zip Entpacker einbinden

  Alt 20. Dez 2008, 17:47
Zitat von MrKnogge:
xZise hast du dir das hier schon mal angeschaut ?

Grüße
Christian
So ich habe es mir jetzt nochmal angeschaut, und naja es funktioniert nicht Woran es genau liegt weiß ich nicht.

So sieht meine Testroutine aus:
Delphi-Quellcode:
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;
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.

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:
if (rep0 >= nowPos64) or (rep0 >= m_DictionarySizeCheck) then begin
  m_OutWindow.Flush();
  result:=false;
  exit;
end;
MfG
xZise
Fabian
Eigentlich hat MS Windows ab Vista den Hang zur Selbstzerstörung abgewöhnt – mkinzler
  Mit Zitat antworten Zitat
Benutzerbild von xZise
xZise

Registriert seit: 3. Mär 2006
Ort: Waldbronn
4.303 Beiträge
 
Delphi 2009 Professional
 
#24

Re: 7-zip Entpacker einbinden

  Alt 4. Aug 2009, 18:30
Hallo,
ich habe versucht das Entpacken zu implementieren. Und ich kann sogar ohne Änderung das nicht kompilieren, weil:
Zitat:
[DCC Fehler] Filelisting.pas(49): E2037 Deklaration von 'SetData' unterscheidet sich von vorheriger Deklaration
[DCC Fehler] Filelisting.pas(240): E2010 Inkompatible Typen: '_WIN32_FIND_DATAA' und '_WIN32_FIND_DATAW'
Meine Frage ist nun, soll Unicode oder Ansi verwendet werden?

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:
FInArchive.Open(FStream, <HIERHIERHIER>, Callback);

function Open(stream: IInStream; const maxCheckStartPosition: PInt64; openArchiveCallback: IArchiveOpenCallback): HRESULT; stdcall;
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.

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
Angehängte Dateien
Dateityp: pas sevenzip_185.pas (21,0 KB, 101x aufgerufen)
Fabian
Eigentlich hat MS Windows ab Vista den Hang zur Selbstzerstörung abgewöhnt – mkinzler
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 3     123   


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 15:07 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