2012-01-17 26 views
7

¿Hay algún componente zip con tales funciones? Necesito descargar un archivo comprimido desde Internet a una transmisión, luego abrir el archivo desde la transmisión y luego extraer archivos a otra transmisión.Delphi: abra un archivo zip de una secuencia -> extraer a una secuencia

E.g. ZipForge puede abrir un archivo de una secuencia ZipForge.OpenArchive(MyStream, false); pero cómo extraer a otro ...?

procedure ExtractToStream(FileName: WideString; Stream: TStream); 

Descripción

Uso ExtractToStream para descomprimir los datos almacenados en el archivo dentro del archivo a un objeto descendiente TStream como TFileStream, TMemoryStream o TBlobStream.

El parámetro FileName especifica el nombre de archivo que se está extrayendo.

Y lo que el uso del método OpenArchive(MyStream, false) si no se admite la extracción ...

Respuesta

19

El componente archivo zip que se construye en XE2 lo hará.

Hay un método Open sobrecargado que recibe un TStream como sus parámetros de entrada.

Para extraer archivos individuales puede llamar a un método Read sobrecargado que pasa el nombre del archivo que desea extraer. El archivo extraído se devuelve como una nueva instancia de TStream. Puede usar CopyFrom en esa instancia para transferir el archivo extraído a la transmisión.

var 
    ZipFile: TZipFile; 
    DownloadedStream, DecompressionStream, MyStream: TStream; 
    LocalHeader: TZipHeader; 
... 
ZipFile := TZipFile.Create; 
try 
    ZipFile.Open(DownloadedStream, zmRead); 
    ZipFile.Read('myzippedfile', DecompressionStream, LocalHeader); 
    try 
    MyStream.CopyFrom(DecompressionStream, DecompressionStream.Size); 
    finally 
    DecompressionStream.Free; 
    end; 
finally 
    ZipFile.Free; 
end; 

Tenga en cuenta que yo no he probado este código, acabo de escribir se basa en el código fuente de TZipFile y la documentación contenida en el código fuente. Puede haber algunas arrugas en esto, pero si el código se comporta como se anuncia, satisface perfectamente sus necesidades.


Bien, ahora lo probé porque tenía curiosidad. Aquí está el programa que muestra que todo esto funciona como se anuncia:

program ZipTest; 

{$APPTYPE CONSOLE} 

uses 
    System.SysUtils, 
    System.Classes, 
    System.Zip; 

procedure ExtractToFile(
    const ZipFileName: string; 
    const ZippedFileIndex: Integer; 
    const ExtractedFileName: string 
); 
var 
    ZipFile: TZipFile; 
    DownloadedStream, DecompressionStream, OutputStream: TStream; 
    LocalHeader: TZipHeader; 
begin 
    DownloadedStream := TFileStream.Create(ZipFileName, fmOpenRead); 
    try 
    ZipFile := TZipFile.Create; 
    try 
     ZipFile.Open(DownloadedStream, zmRead); 
     ZipFile.Read(ZippedFileIndex, DecompressionStream, LocalHeader); 
     try 
     OutputStream := TFileStream.Create(ExtractedFileName, fmCreate); 
     try 
      OutputStream.CopyFrom(DecompressionStream, DecompressionStream.Size); 
     finally 
      OutputStream.Free; 
     end; 
     finally 
     DecompressionStream.Free; 
     end; 
    finally 
     ZipFile.Free; 
    end; 
    finally 
    DownloadedStream.Free; 
    end; 
end; 

begin 
    try 
    ExtractToFile('C:\desktop\test.zip', 0, 'C:\desktop\out.txt'); 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
end. 

Tenga en cuenta que extraje de índice en lugar de nombre de archivo, ya que era más conveniente para mí. Y usé secuencias de archivos en lugar de flujos de memoria que imagino que usaría. Sin embargo, dado que los métodos TZipFile funcionan con TStream, estoy seguro de que el código funcionará con flujos de cualquier forma.


Ésta es la última de una serie de preguntas sobre archivos ZIP. Sé que está utilizando XE2 y me pregunto por qué parece reacio a utilizar la clase ZIP incorporada que proporciona XE2. No he visto nada que indique que no cumplirá con sus requisitos. De hecho, es precisamente esta capacidad de trabajar directamente con flujos lo que me hace sentir que tiene suficiente generalidad para cualquier aplicación.

+1

Muchas gracias David !!! – maxfax

+0

No vi el método Read (lo comprobé rápidamente), hay información pura al respecto http://docwiki.embarcadero.com/VCL/en/System.Zip.TZipFile.Lee – maxfax

+0

@maxfax ¿Qué edición de Delphi tienes? Tengo Pro y eso viene con la fuente. Mis respuestas a ambas preguntas ZIP recientes se basan completamente en la lectura de la fuente. Sé exactamente nada sobre los archivos ZIP y nada sobre este componente. Si tienes el código fuente, creo que será una gran ayuda para ti. –

Cuestiones relacionadas