Inicio > Delphi, Ejemplos, XE2 > Testeando XE2… (soporte nativo para ficheros ZIP)

Testeando XE2… (soporte nativo para ficheros ZIP)



Miércoles, 14 de septiembre de 2011

ZIPFile   Otra de las nuevas funcionalidades que trae la versión de XE2 es el soporte para ficheros ZIP. No es que sea especialmente transcendental, pero en mi caso la he utilizado bastante en mis desarrollos y hasta ahora lo había tenido que hacer mediante componentes externos (he  probado varios paquetes).

   Para ello se ha añadido a la unit System.ZIP, todo lo necesario para el trabajo con este tipo de ficheros.

   En sistema de trabajo es bastante sencillo. Para trabajar con un fichero de este tipo tenemos que crear un objeto de la clase TZIPFile y abrirlo (utilizando la función Open). Tenemos diferentes modos de apertura dependiendo de las operaciones a realizar con el fichero (read,write o readwrite).

0
1
2
// Abrir un fichero
procedure Open(ZipFileName: string; OpenMode: TZipMode); overload;
procedure Open(ZipFileStream: TStream; OpenMode: TZipMode); overload;

Una vez abierto el fichero, podemos utilizar las operaciones básicas.
Extraer ficheros existentes dentro del archivo:

0
1
2
3
4
// Extraer un fichero sobre una ubicación
procedure Extract(FileName: string; Path: string = '';
                  CreateSubdirs: Boolean=True); overload;
procedure Extract(Index: Integer; Path: string = '';
                  CreateSubdirs: Boolean=True); overload;

O extraerlos todos:

0
1
// extraerlos todos hacia un directorio
procedure ExtractAll(Path: string = '');

Añadir ficheros a un archivo comprimido existente:

0
1
2
// Añadir ficheros a un archivo comprimido
procedure Add(FileName: string; ArchiveFileName: string = '';
              Compression: TZipCompression = zcDeflate); overload;

(esta tienen bastantes variantes sobrecargadas con diferentes parámetros)

Y también podemos comprobar la integridad de un fichero comprimido existente mediante la función IsValid (que en este caso está definida como función de clase).

0
class function IsValid(ZipFileName: string): Boolean; static;

No son todas las funciones, pero sí las básicas; También hay algunas más definidas como procedimientos de clase, que nos permiten realizar operaciones de forma más sencilla y/o rápida.

Para ponerlo en práctica y probarlo he realizado un sencillo ejemplo que incluye las operaciones básicas; Y podéis comprobar que con pocas líneas es fácil hacer casi todo lo que se espera de estos ficheros.

 

TestZIPFile

Por ejemplo, el código para extraer todo el contenido sobre un directorio seleccionado es el siguiente:

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
procedure TForm3.ActionExtractExecute(Sender: TObject);
var
  b:boolean;
  DirOut:String;
begin
  // El nombre es vacío?
  if (zipFileName = '') then begin
    // Abrir uno
    ActionOpen.Execute;
    // Correcto?
    if (zipFileName = '') then begin
      Exit;
    end;
  end;
 
  // Es Valido
  b := xf.IsValid(zipFileName);
 
  // no correcto?
  if not (b) then begin
    MessageDlg('Error al abrir el fichero. Parece que es' +
               ' incorrecto o está corrupto.',
               mtError, [mbOK], 0);
    exit;
  end;
 
  // Extraer  // Path de salida
  b := SelectDirectory('Seleccione el directorio para extraer ficheros',
                       '', DirOut);
  if (b) then begin
    // protección
    try
      // Extraer al directorio seleccionado
      xf.Open(zipFileName, zmRead);
      xf.ExtractAll(DirOut);
      xf.Close;
      MessageDlg('La extracción se ha producido correctamente',
        mtInformation, [mbOK], 0);
    except
      MessageDlg('Se ha producido un error al extraer los ficheros.',
        mtError, [mbOK], 0);
    end;
  end;
end;

El código para añadir uno o varios ficheros seleccionados en un OpenDialog sería similar a este:

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
procedure TForm3.ActionAddFilesExecute(Sender: TObject);
var
  b:Boolean;
  i:integer;
begin
 
  // No está creado?
  if not Assigned(xf) then begin
    // Si no lo está lo creamos
    ActionNuevoZIPExecute(nil);
  end;
  // Selecciconar ficheros a añadir
  b :=  OpenDialog1.Execute;
  if (b) then begin
    // Abrirlo
    xf.Open(zipFileName, zmReadWrite);
 
    // Para 1 fichero
    //     xf.Add(OpenDialog1.FileName);
 
    // Para n ficheros
    for i := 0 to (OpenDialog1.Files.Count - 1) do begin
      xf.Add(OpenDialog1.Files[i]);
    end;
    // cerrar
    xf.Close;
  end;
  // Actualizar la pantalla
  _UpdateFiles();
end;

Para cada fichero que hay incluído en un archivo ZIP contamos con una estructura que nos permite acceder a todas la información de forma rápida. Definido como packed record, en System.ZIP podéis encontrar la definición completa y la documentación de esta estructura:

Podéis revisar el código completo del ejemplo; Está disponible aquí y podéis descargarlo junto con el fichero  compilado.

[SOURCES + BIN]

Un saludo.

Delphi, Ejemplos, XE2 , , ,

  1. Jueves, 15 de septiembre de 2011 a las 08:56 | #1

    No está mal, pero es incómodo. Prefiero el soporte para TAR y GZip que tiene Free Pascal (http://lazarus-ccr.sourceforge.net/fpcdoc/fcl/libtar/ y http://lazarus-ccr.sourceforge.net/fpcdoc/fcl/zstream/ respectivamente), que te permiten acceder al contenido de paquetes .tar y .tar.gz usando TStream, sin tener que extraer previamente los archivos.

    Estaría bien que Delphi lo incluyera, en especial si realmente quiere hacerse un hueco en los sistemas POSIX (creo que MacOS también tiene soporte nativo para TAR y GZip)

  2. Neftalí
    Jueves, 15 de septiembre de 2011 a las 09:05 | #2

    @Ñuño Martínez
    Aunque he puesto las cabeceras de algunas funciones, no he colocado todas las que hay en la unit System.ZIP. Entre las que no he puesto, se encuentran algunas para trabajar también con Streams.

    El tema de los diferentes formatos, pues supongo que como todo; Hay que tener en cuenta que es una primera versión.
    Esperemos, que como en otros muchos aspectos, la cosas se vayan ampliando…

  3. Jueves, 15 de septiembre de 2011 a las 10:56 | #3

    Amigo, si la clase tiene métodos para acceder a un archivo concreto para leerlo con un TStream, entonces mi queja es menor. Y si también permite insertar datos del mismo modo, pues entonces grito todavía menos.

    Sólo queda, entonces, lo del formato, Pero eso ya es otro tema. En última instancia siempre se puede adaptar las clases de la FCL a Delphi, ¿no?

  4. Neftalí
    Jueves, 15 de septiembre de 2011 a las 11:39 | #4

    @Ñuño Martínez
    Sí que los tiene sí.
    No los puse por no colocar todos, pero tanpo para añadir como para extraer están.

  5. German
    Martes, 20 de septiembre de 2011 a las 06:48 | #5

    Creo que la única pega que pondría sobre esta clase sería los eventos… ya que no dispone de ninguno y es imposible mostrar una barra de proceso, totalmente necesaria en mi opinión, para trabajar con archivos grandes.

    Salu2.

  6. Neftalí
    Martes, 20 de septiembre de 2011 a las 09:15 | #6

    @German
    Hola Germán.
    Efectívamente. Como ya he comentado es un paquete básico. Válido seguramente para la mayoría de ocasiones, pero no para todas.

    Un saludo.

  7. Alejandro
    Miércoles, 9 de enero de 2013 a las 18:58 | #7

    Amigo Neftalí, que paquetes has probado para el manejo de archivos comprimidos. Necesito manejar esos archivos usando la versión 10 de Delphi.

    Espero que me puedas recomendar alguno que sea relativamente bueno y en lo posible gratis.

  8. Neftalí
    Miércoles, 9 de enero de 2013 a las 19:17 | #8

    @Alejandro
    Hola Alejandro.
    A parte de este comentado en el artículo, he utilizado durante mucho tiempo ZipMaster (http://www.delphizip.org/) que creo que es compatible con todas las versiones de delphi y posee las acciones necesarias para realizar todo lo que necesites con ficheros comprimidos.
    Es este entrada del blog de Juan Antonio Castillo también tienes información sobre otro paquete (http://jachguate.wordpress.com/2012/12/10/7zip-y-delphi/)

    Un saludo.

  9. joan
    Jueves, 18 de abril de 2013 a las 14:36 | #9

    la fecha no te la pone bien alguien podra arreglarlo?? y que te de la medida en mega Bytes plis

  10. Neftalí
    Jueves, 18 de abril de 2013 a las 15:14 | #10

    @joan
    ¿Puedes explicarte mejor Joan?
    ¿Podrías poner un ejemplo del error?
    Se puede mirar en QC para ver si es un bug conocido y si hay solución publicada.

  1. Lunes, 10 de diciembre de 2012 a las 07:17 | #1
What is 2 + 2 ?
Please leave these two fields as-is:
IMPORTANTE! Para continuar, debes resolver la siguiente suma (para saber si eres humano) :-)
Por favor escriba los caracteres de la imagen captcha en el cuadro de entrada

Por favor, rellena los caracteres de la imagen en el cuadro de texto (ANTI-SPAM)
ATRAS - para acceder al texto del comentario en caso de fallo.
_____________________________________________________________________