8
votes

Freeware ZIP Composant pour Delphi 2010 / Delphi Xe?

Connaissez-vous un composant libre, compatible avec Delphi 2010 ou xe pour gérer les archives zip (en réalité, seulement lire des articles d'archive et extraire des fichiers requis)?

S'il vous plaît pas de bêta.

J'ai pensé à Zipforge de ComponceAce, mais c'est gratuit uniquement pour un usage personnel. Aucune distribution de logiciels autorisée.


3 commentaires

Avez-vous seulement besoin de codage / décodage ou les deux?


@Ritsaert Hornstra bien, les deux, je crois.


Remarque: Démarrage avec Delphi Xe2 Prise en charge des fichiers Zip a été ajouté: [ docwiki.embarcadero.com/libries/seattle/fr/... ] [ DELPHIBLOG.TWODESK.COM/NATIVE-ZIP-FILE-SUPPORT-IN-DELPHIMPHIMPHIMHIXE2 ] Cela leur a fallu un moment!


7 Réponses :


16
votes

Vous pouvez obtenir le Turbopower Abbrevia pour 2010 à partir de: http://tpabbrevia.sourceforge.net/


2 commentaires

TURBOPOWER ABBREVIA DONNÉES COMPRESSION SEP 09 2008 Il semble ne pas être testé ni mis à jour pour Delphi 2010 :(


J'ai mis à jour l'URL depuis que la version d'AbRevia sur Sourceforge prend en charge Delphi 2010 / XE et a des tests unitaires.



4
votes

Vous pouvez regarder Ceci si vous aimez 7ZIP


3 commentaires

Il manque un peu d'informations sur cette page. Il y a ce lien: 7-zip.org/sdk.html mais cela ne gérer l'API à 7z.dll, et j'ai lu une interface COM 7za.dll (en d'autres termes: a une bibliothèque de type à importer)


Oui, cela est prometteur. Merci!


J'accepte cette réponse. C'est juste intéressant et utile pour moi. Merci.



1
votes

2 commentaires

Tzipmaster (avant la version V1.79) ne peut pas être construit avec succès dans la D2009. Bien que cette version de 1.79 fonctionnera ensuite dans l'environnement Unicode, il a toujours les mêmes limitations que les versions précédentes. Il n'est pas compatible avec D2010 également ou n'est pas testé.


Zipmaster semble être maintenant compatible, au moins, je vois des bugses dans les nouvelles. Merci de suggestion!



0
votes

DotNetZip est une bibliothèque de code géré (.NET), qui expose une interface COM.

gratuit.
Open Source
MS-Pl sous licence.


1 commentaires

Mauvaise plate-forme et trop de surcharge de code pour une application DELPHI.



1
votes

Si la distribution d'une DLL ActiveX avec votre projet n'est pas un problème pour vous, alors Chilkat Zip (http://www.chilkatsoft.com/zip-activex.asp) semble faire le tour. Les exemples DELPHI sont ici: http://www.example-code.com/delphi/zip. ASP


0 commentaires

3
votes

Si vous n'avez besoin que de décodage (développé pour Delphi 2007, pas encore testé sous Delphi 2010 / XE):

unit UnitZip;

interface

uses
  SysUtils, Classes;

type
  EZipException = class( Exception );

  TZipFileInfo = record
    LastModified:                      TDateTime;
    Crc32:                             Longword;
    CompressedSize:                    Longword;
    UncompressedSize:                  Longword;
  end;

  TZipFileReader = class
  private
    // Information about the memory mapped file
    FFileHandle:                       THandle;
    FFileMapping:                      THandle;
    FMappedAddress:                    Pointer;
    // Location of the ZIPfile in memory. Currently we only support memory mapped ZIPfiles without disk spanning.
    FStart:                            Pointer;
    FSize:                             Longword;
    // ZIP file contents
    FFilenames:                        TStrings;
    function    GetZipFileInfo         ( const FileName: AnsiString ): TZipFileInfo;
  public
    constructor Create                 ( const FileName: string; ZipStartOffset: Int64 = 0; Size: Longword = 0 ); overload;
    constructor Create                 ( const ResourceName, ResourceType: string; Instance: HMODULE = 0 ); overload;
    constructor Create                 ( Buffer: Pointer; Size: Longword ); overload;
    destructor  Destroy;               override;
    function    GetFile                ( const FileName: string ): TBytes; overload;
    function    GetFile                ( FileID: Integer ): TBytes; overload;
    property    FileNames:             TStrings read FFileNames;
    property    FileInfo               [ const FileName: AnsiString ]: TZipFileInfo read GetZipFileInfo;
  end;

implementation

uses
  ZLib, Windows;

const
  cResourceNotFound   = 'Resource not found: %s.%s.';
  cResourceNotLoaded  = 'Resource not loaded: %s.%s.';
  cCannotOpenFile     = 'Cannot open file %s: OS error: %d.';
  cCannotGetFileSize  = 'Cannot get file size of file %s: OS error: %d.';
  cCannotMapFile      = 'Cannot create file mapping of file %s: OS error: %d.';
  cZipFileTooSmall    = 'ZIP file is too small.';
  cZipFileFormatError = 'ZIP file is invalid.';
  cZipBufferInvalid   = 'ZIP memory buffer is invalid.';
  cUnsupportedMethod  = 'ZIP unsupported compression method: %d.';
  cFileNotFoundInZip  = 'File not found in ZIP content: %s';

// ZIP file format records.
// The generic zip file format is ( TLocalFileHeader; Name; Extra; compressed data )* ( TFileHeader; Name; Extra; Remark )* TLastHeader

type
  TFileInfo = packed record
    NeededVersion:                     Word;            // 20
    Flags:                             Word;            // 1=Text,4=extra present
    ZipMethod:                         Word;            // 0=stored 8=deflate
    LastModified:                      Longword;        // time in dos format or Unix Timestamp
    Crc32:                             Longword;
    CompressedSize:                    Longword;
    UncompressedSize:                  Longword;
    NameSize:                          Word;
    ExtraSize:                         Word;
  end;

  TFileHeader = packed record
    Signature:                         Longword;        // $02014b50 PK#1#2
    MadeBy:                            Word;            // Version number, 20
    FileInfo:                          TFileInfo;
    CommentSize:                       Word;            // 0
    FirstDiskNumber:                   Word;            // 0
    IntFileAttr:                       Word;            // 0 = binary; 1 = text
    ExtFileAttr:                       Longword;        // DOS file attributes (Archived=32)
    LocalFileHeaderHeadOff:            Longword;        // @TLocalFileHeader
  end;
  PFileHeader = ^TFileHeader;

  TLocalFileHeader = packed record
    Signature:                         Longword;        // $02014b50 PK#3#4
    FileInfo:                          TFileInfo;
  end;
  PLocalFileHeader = ^TLocalFileHeader;

  TLastHeader = packed record
    Signature:                         Longword;        // $02014b50 PK#5#6
    ThisDiskNumber:                    Word;
    CentralDirDisk:                    Word;
    ThisDiskFileCount:                 Word;
    TotalFileCount:                    Word;
    FileHeaderSize:                    Longword;
    FileHeaderOffset:                  Longword;
    CommentSize:                       Word;
  end;
  PLastHeader = ^TLastHeader;

const
  MagicLastHeader  = $06054b50;
  MagicLocalHeader = $04034b50;
  MagicFileHeader  = $02014b50;

type
  IntPtr = Longword; // NativeInt on Delphi2007 is an Int64 ??

{$if CompilerVersion < 19}
procedure SetAnsiString( var S: AnsiString; P: PAnsiChar; L: Integer ); inline;
begin
  SetString( S, P, L );
end;
{$ifend}

{ TZipFileReader }

constructor TZipFileReader.Create( const FileName: string; ZipStartOffset: Int64; Size: Longword );
begin
  // Open the file in question.
  FFileHandle := CreateFile( PChar( FileName ), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0 );
  if FFileHandle = INVALID_HANDLE_VALUE then raise EZipException.CreateFmt( cCannotOpenFile, [ Filename, GetLastError() ] );
  if Size = 0 then Size := GetFileSize( FFileHandle, nil );
  if Size = INVALID_FILE_SIZE then raise EZipException.CreateFmt( cCannotGetFileSize, [ Filename, GetLastError() ] );

  try
    // Create a file mapping of the file in question
    FFileMapping := CreateFileMapping( FFileHandle, nil, PAGE_READONLY, 0, 0, nil);
    if FFileMapping = 0 then raise EZipException.CreateFmt( cCannotMapFile, [ Filename, GetLastError() ] );

    try
      // Get the file mapped in memory (NOTE: The offset needs to be on the  memory allocation granularity of the system)
      // Hence we assign it it's own pointer -> todo rounding etc.
      FMappedAddress := MapViewOfFile( FFileMapping, FILE_MAP_READ, Int64Rec( ZipStartOffset ).Hi, Int64Rec( ZipStartOffset ).Lo, Size );
      if not Assigned( FMappedAddress ) then EZipException.CreateFmt( cCannotMapFile, [ Filename, GetLastError() ] );
      Create( FMappedAddress, Size );
    except
      CloseHandle( FFileMapping );
      FFileMapping := 0;
      raise;
    end;
  except
    CloseHandle( FFileHandle );
    FFileHandle := 0;
    raise;
  end;
end;

constructor TZipFileReader.Create( const ResourceName, ResourceType: string; Instance: HMODULE );
var
  Resource: HRSRC;
  Global:   HGLOBAL;
begin
  Resource := FindResource( Instance, PChar( ResourceName ), PChar( ResourceType ) );
  if Resource = 0 then raise EZipException.CreateFmt( cResourceNotFound, [ ResourceName, ResourceType ] );
  Global := LoadResource( Instance, Resource );
  if Global = 0 then raise EZipException.CreateFmt( cResourceNotLoaded, [ ResourceName, ResourceType ] );
  Create( LockResource( Global ), SizeofResource( HInstance, Resource ) );
  // Note: kb57808: SizeofResource() returns the resource size rounded up to the alignment size.
end;

constructor TZipFileReader.Create( Buffer: Pointer; Size: Longword );
var
  LastHeader: PLastHeader;
  FileHeader: PFileHeader;
  i, Off:     Longword;
  Name:       AnsiString;
begin
  // Note the location.
  FStart := Buffer;
  FSize  := Size;

  // Some sanity checks.
  if FSize < sizeof( TLocalFileHeader ) + sizeof( TFileHeader ) + sizeof( TLastHeader ) then raise EZipException.Create( cZipFileTooSmall );
  if IsBadReadPtr( Buffer, Size ) then raise EZipException.Create( cZipBufferInvalid );
  if PLongword( Buffer )^ <> MagicLocalHeader then raise EZipException.Create( cZipFileFormatError );

  // Find the last header. Due to the alignment of SizeofResource, we need o search for it.
  LastHeader := Pointer( IntPtr( Buffer ) + Size - sizeof( TLastHeader ) );
  for i := 0 to 31 do begin
    if LastHeader^.Signature = MagicLastHeader then Break;
    Dec( IntPtr( LastHeader ) );
  end;
  if LastHeader^.Signature <> MagicLastHeader then raise EZipException.Create( cZipFileFormatError );

  FFilenames := TStringList.Create();

  Off := LastHeader^.FileHeaderOffset;
  for i := 0 to LastHeader^.TotalFileCount - 1 do begin
    // Get header
    if Off + sizeof( TFileHeader ) >= Size then raise EZipException.Create( cZipFileFormatError );
    FileHeader := Pointer( IntPtr( Buffer ) + Off );
    Inc( Off, sizeof( TFileHeader ) );
    if FileHeader^.Signature <> MagicFileHeader then raise EZipException.Create( cZipFileFormatError );

    // Get filename
    if Off + FileHeader^.FileInfo.NameSize + FileHeader^.FileInfo.ExtraSize >= Size then raise EZipException.Create( cZipFileFormatError );
    SetAnsiString( Name, Pointer( IntPtr( Buffer ) + Off ), FileHeader^.FileInfo.NameSize );
    Inc( Off, FileHeader^.FileInfo.NameSize + FileHeader^.FileInfo.ExtraSize );

    // Save filename and offset into ZIPfile where it can be found.
    FFileNames.AddObject( Name, Pointer( FileHeader^.LocalFileHeaderHeadOff ) );
  end;
  // For quick access.
  TStringList( FFilenames ).Sorted := True;

end;

destructor TZipFileReader.Destroy;
begin
  if Assigned( FMappedAddress ) then UnmapViewOfFile( FMappedAddress );
  if FFileMapping <> 0 then CloseHandle( FFileMapping );
  if FFileHandle  <> 0 then CloseHandle( FFileHandle  );
  inherited Destroy;
end;

function TZipFileReader.GetFile( const FileName: string ): TBytes;
var
  ID: Integer;
begin
  // Convert filename in FileID and access by ID.
  ID := FFilenames.IndexOf( FileName );
  if ID < 0 then raise EZipException.CreateFmt( cFileNotFoundInZip, [ FileName ] );
  Result := GetFile( ID );
end;

function TZipFileReader.GetFile( FileID: Integer ): TBytes;
var
  Off:   Longword;
  Local: PLocalFileHeader;
  ZRec:  TZStreamRec;
const
  ZLibHeader: array [ 0..1 ] of Byte = ( $78, $01 ); // Deflate 32KB window size no preset dictionary.
begin
  // Sanity check
  if ( FileID < 0 ) or ( FileID >= FFilenames.Count ) then raise EZipException.CreateFmt( 'Invalid File ID: %d', [ FileID ] );

  // Get the file header and perform sanity check
  Off := Longword( FFilenames.Objects[ FileID ] );
  if Off + sizeof( TLocalFileHeader ) >= FSize then raise EZipException.Create( cZipFileFormatError );
  Local := Pointer( IntPtr( FStart ) + Off );
  if Local^.Signature <> MagicLocalHeader then raise EZipException.Create( cZipFileFormatError );
  Inc( Off, sizeof( TLocalFileHeader ) + Local^.FileInfo.NameSize + Local^.FileInfo.ExtraSize );
  if Off + Local^.FileInfo.CompressedSize >= FSize then raise EZipException.Create( cZipFileFormatError );
  // note: should we check the name again?

  SetLength( Result, Local^.FileInfo.UncompressedSize );
  if Length( Result ) > 0 then case Local^.FileInfo.ZipMethod of
    0:   begin // STORED
           if Local^.FileInfo.CompressedSize <> Local^.FileInfo.UncompressedSize then raise EZipException.Create( cZipFileFormatError );
           Move( Pointer( IntPtr( FStart ) + Off )^, Result[ 0 ], Local^.FileInfo.UncompressedSize );
         end;
    8:   begin // DEFLATE
           ZeroMemory( @ZRec, sizeof( ZRec ) );
           ZRec.next_in   := @ZLibHeader;
           ZRec.avail_in  := sizeof( ZLibHeader );
           ZRec.total_in  := sizeof( ZLibHeader ) + Local^.FileInfo.CompressedSize;
           ZRec.next_out  := @Result[ 0 ];
           ZRec.avail_out := Local^.FileInfo.UncompressedSize;
           ZRec.total_out := Local^.FileInfo.UncompressedSize;
           ZRec.zalloc    := zlibAllocMem;
           ZRec.zfree     := zlibFreeMem;
           if inflateInit_( ZRec, zlib_Version, sizeof( ZRec ) ) <> 0 then raise EZipException.Create( cZipFileFormatError );
           try
             if not( inflate( ZRec, Z_FULL_FLUSH ) in [ Z_OK, Z_STREAM_END ] ) then raise EZipException.Create( cZipFileFormatError );
             ZRec.next_in   := Pointer( IntPtr( FStart ) + Off );
             ZRec.avail_in  := Local^.FileInfo.CompressedSize;
             if not( inflate( ZRec, Z_FINISH ) in [ Z_OK, Z_STREAM_END ] ) then raise EZipException.Create( cZipFileFormatError );
           finally
             inflateEnd( ZRec );
           end;
         end;
    else raise EZipException.CreateFmt( cUnsupportedMethod, [ Local^.FileInfo.ZipMethod ] );
  end;

  // todo: CRC32 sanity check if requested.
end;

function TZipFileReader.GetZipFileInfo( const FileName: AnsiString ): TZipFileInfo;
var
  FileID: Integer;
  Off:    Longword;
  Local:  PLocalFileHeader;
begin
  // Get the correct file ID
  FileID := FFilenames.IndexOf( FileName );
  if FileID < 0 then raise EZipException.CreateFmt( cFileNotFoundInZip, [ FileName ] );

  // Get the file header and perform sanity check
  Off := Longword( FFilenames.Objects[ FileID ] );
  if Off + sizeof( TLocalFileHeader ) >= FSize then raise EZipException.Create( cZipFileFormatError );
  Local := Pointer( IntPtr( FStart ) + Off );
  if Local^.Signature <> MagicLocalHeader then raise EZipException.Create( cZipFileFormatError );
  Inc( Off, sizeof( TLocalFileHeader ) + Local^.FileInfo.NameSize + Local^.FileInfo.ExtraSize );
  if Off + Local^.FileInfo.CompressedSize >= FSize then raise EZipException.Create( cZipFileFormatError );

  // Return requested data.
  Result.LastModified     := Local^.FileInfo.LastModified;
  Result.Crc32            := Local^.FileInfo.Crc32;
  Result.CompressedSize   := Local^.FileInfo.CompressedSize;
  Result.UncompressedSize := Local^.FileInfo.UncompressedSize;
end;

end.


0 commentaires

3
votes

Jetez un coup d'œil à cette openSource Unité Synzip . Il est encore plus rapide de la décompression que l'unité par défaut expédiée avec Delphi et générera un EXE plus petit (les tables CRC sont créées au démarrage).

aucune DLL externe n'est nécessaire.

Je viens de faire des modifications pour gérer les noms de fichier Unicode à l'intérieur du contenu zip, non seulement Win-ansi Charset, mais également des caractères unicodes. Les commentaires sont les bienvenus.


0 commentaires