⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sxziputils.pas

📁 skin components for design of your applicastions
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit SXZipUtils;

////////////////////////////////////////////////////////////////////////////////
// SXSkinComponents: Skinnable Visual Controls for Delphi and C++Builder      //
//----------------------------------------------------------------------------//
// Version: 1.2.1                                                             //
// Author: Alexey Sadovnikov                                                  //
// Web Site: http://www.saarixx.info/sxskincomponents/                        //
// E-Mail: sxskincomponents@saarixx.info                                      //
//----------------------------------------------------------------------------//
// LICENSE:                                                                   //
// 1. You may freely distribute this file.                                    //
// 2. You may not make any changes to this file.                              //
// 3. The only person who may change this file is Alexey Sadovnikov.          //
// 4. You may use this file in your freeware projects.                        //
// 5. If you want to use this file in your shareware or commercial project,   //
//    you should purchase a project license or a personal license of          //
//    SXSkinComponents: http://saarixx.info/sxskincomponents/en/purchase.htm  //
// 6. You may freely use, distribute and modify skins for SXSkinComponents.   //
// 7. You may create skins for SXSkinComponents.                              //
//----------------------------------------------------------------------------//
// Copyright (C) 2006-2007, Alexey Sadovnikov. All Rights Reserved.           //
////////////////////////////////////////////////////////////////////////////////

interface

{$I Compilers.inc}

uses SysUtils, Classes, Types, Windows;

type

  TCommonFileHeader=packed record
   VersionNeededToExtract:Word;
   GeneralPurposeBitFlag:Word;
   CompressionMethod:Word;
   LastModFileTimeDate:DWORD;
   Crc32:DWORD;
   CompressedSize:DWORD;
   UncompressedSize:DWORD;
   FilenameLength:Word;
   ExtraFieldLength:Word;
  end;

  TLocalFile=packed record
   LocalFileHeaderSignature:DWORD;
   CommonFileHeader:TCommonFileHeader;
   FileName:String;
   ExtraField:String;
   CompressedData:String;
  end;

  TFileHeader=packed record
   CentralFileHeaderSignature:DWORD;
   VersionMadeBy:Word;
   CommonFileHeader:TCommonFileHeader;
   FileCommentLength:Word;
   DiskNumberStart:Word;
   InternalFileAttributes:Word;
   ExternalFileAttributes:DWORD;
   RelativeOffsetOfLocalHeader:DWORD;
   FileName:String;
   ExtraField:String;
   FileComment:String;
  end;

  TEndOfCentralDir=packed record
   EndOfCentralDirSignature:DWORD;
   NumberOfThisDisk:Word;
   NumberOfTheDiskWithTheStart:Word;
   TotalNumberOfEntriesOnThisDisk:Word;
   TotalNumberOfEntries:Word;
   SizeOfTheCentralDirectory:DWORD;
   OffsetOfStartOfCentralDirectory:DWORD;
   ZipfileCommentLength:Word;
  end;

  TZipFile=class(TObject)
    Files:array of TLocalFile;
    CentralDirectory:array of TFileHeader;
    EndOfCentralDirectory:TEndOfCentralDir;
    ZipFileComment:String;
   private
    function GetUncompressed(I:Integer):String;
    procedure SetUncompressed(I:Integer;const Value:String);
    function GetDateTime(I:Integer):TDateTime;
    procedure SetDateTime(I:Integer;const Value:TDateTime);
    function GetCount:Integer;
    function GetName(I:Integer):String;
    procedure SetName(I:Integer;const Value:String);
   public
    procedure WriteFileToStream(Stream:TStream;FileName:String);
    property Count:Integer read GetCount;
    procedure AddFile(const Name:String;FAttribute:DWORD=0);
    procedure SaveToFile(const FileName:String);
    procedure SaveToStream(ZipFileStream:TStream);
    procedure LoadFromFile(const FileName:String);
    procedure LoadFromStream(const ZipFileStream:TStream);
    property Data[I:Integer]:String read GetUncompressed write SetUncompressed;
    property DateTime[I:Integer]:TDateTime read GetDateTime write SetDateTime;
    property Name[I:Integer]:String read GetName write SetName;
  end;

  TSXPreloadedZipFile=class
   public
    FullPath:String;
    FileName:String;
    ZipFile:TZipFile;
    SkinLibrary:Pointer;
    constructor Create;
    destructor Destroy; override;
  end;

  TSXPreloadedZipFileList=class
   protected
    FItem:TList;
    function Get(const Index:Integer):TSXPreloadedZipFile;
    procedure Put(const Index:Integer;const Item:TSXPreloadedZipFile);
    function GetCount:Integer;
   public
    procedure Add(ZipFile:TSXPreloadedZipFile);
    function GetZipFileIndex(const FileName:String):Integer;
    procedure Delete(const Index:Integer);
    procedure Clear;
    constructor Create;
    destructor Destroy; override;
    property Item[const Index:Integer]:TSXPreloadedZipFile read Get write Put; default;
    property Count:Integer read GetCount;
  end;

  EZipFileCRCError=class(Exception);

function ZipCRC32(const Data:String):Cardinal;

function PreloadZipFile(Stream:TStream;const FilePath:String;
           SkinLibrary:Pointer):TZipFile;
function GetPreloadedZipFile(SkinLibrary:Pointer;const FilePath:String):TZipFile;
procedure DeletePreloadedZipFiles(SkinLibrary:Pointer);
function ExtractZipPath(var FilePath,ZipPath:String):Boolean;

var PreloadedZipFiles:TSXPreloadedZipFileList;

implementation

uses SXSkinUtils, SXSkinLibrary, SXZLibCompress;

{ TZipFile }

procedure TZipFile.SaveToFile(const FileName:String);
var ZipFileStream:TFileStream;
begin
 ZipFileStream:=TFileStream.Create(FileName,fmCreate);
 try
  SaveToStream(ZipFileStream);
 finally
  ZipFileStream.Free;
 end;
end;

procedure TZipFile.SaveToStream(ZipFileStream:TStream);
var I:Integer;
begin
 for I:=0 to High(Files) do
  with Files[i] do
   begin
    CentralDirectory[I].RelativeOffsetOfLocalHeader:=ZipFileStream.Position;
    ZipFileStream.Write(LocalFileHeaderSignature,4);
    if LocalFileHeaderSignature=$04034B50 then
     begin
      ZipFileStream.Write(CommonFileHeader,sizeof(CommonFileHeader));
      ZipFileStream.Write(PChar(FileName)^,CommonFileHeader.FilenameLength);
      ZipFileStream.Write(PChar(extrafield)^,CommonFileHeader.ExtraFieldLength);
      ZipFileStream.Write(PChar(CompressedData)^,CommonFileHeader.CompressedSize);
     end;
   end;
 EndOfCentralDirectory.OffsetOfStartOfCentralDirectory:=ZipFileStream.Position;
 for I:=0 to High(CentralDirectory) do
  with CentralDirectory[i] do
   begin
    ZipFileStream.Write(CentralFileHeaderSignature,4);
    ZipFileStream.Write(VersionMadeBy,2);
    ZipFileStream.Write(CommonFileHeader,sizeof(CommonFileHeader));
    ZipFileStream.Write(FileCommentLength,2);
    ZipFileStream.Write(DiskNumberStart,2);
    ZipFileStream.Write(InternalFileAttributes,2);
    ZipFileStream.Write(ExternalFileAttributes,4);
    ZipFileStream.Write(RelativeOffsetOfLocalHeader,4);
    ZipFileStream.Write(PChar(FileName)^,length(FileName));
    ZipFileStream.Write(PChar(ExtraField)^,length(ExtraField));
    ZipFileStream.Write(PChar(FileComment)^,length(FileComment));
   end;
 with EndOfCentralDirectory do
  begin
   EndOfCentralDirSignature:=$06054B50;
   NumberOfThisDisk:=0;
   NumberOfTheDiskWithTheStart:=0;
   TotalNumberOfEntriesOnThisDisk:=High(Files)+1;
   TotalNumberOfEntries:=High(Files)+1;
   SizeOfTheCentralDirectory:=ZipFileStream.Position-OffsetOfStartOfCentralDirectory;
   ZipfileCommentLength:=length(ZipFileComment);
  end;
 ZipFileStream.Write(EndOfCentralDirectory,sizeof(EndOfCentralDirectory));
 ZipFileStream.Write(PChar(ZipFileComment)^,length(ZipFileComment));
end;

procedure TZipFile.LoadFromStream(const ZipFileStream:TStream);
var Signature:DWORD;
            N:Integer;
begin
 N:=0;
 repeat
  Signature:=0;
  ZipFileStream.Read(Signature,4);
  if ZipFileStream.Position=ZipFileStream.Size then exit;
 until Signature=$04034B50;
 repeat
  if Signature=$04034B50 then
   begin
    Inc(N);
    SetLength(Files,N);
    SetLength(CentralDirectory,N);
    with Files[N-1] do
     begin
      LocalFileHeaderSignature:=Signature;
      ZipFileStream.Read(CommonFileHeader,sizeof(CommonFileHeader));
      SetLength(FileName,CommonFileHeader.FilenameLength);
      ZipFileStream.Read(PChar(FileName)^,CommonFileHeader.FilenameLength);
      FileName:=StringReplace(FileName,'\','/',[rfReplaceAll]);
      
      SetLength(ExtraField,CommonFileHeader.ExtraFieldLength);
      ZipFileStream.Read(PChar(ExtraField)^,CommonFileHeader.ExtraFieldLength);
      SetLength(CompressedData,CommonFileHeader.CompressedSize);
      ZipFileStream.Read(PChar(CompressedData)^,CommonFileHeader.CompressedSize);
     end;
   end;
  Signature:=0;
  ZipFileStream.Read(Signature,4);
 until Signature<>$04034B50;
 N:=0;
 repeat
  if Signature=$02014B50 then
   begin
    Inc(N);
    with CentralDirectory[N-1] do
     begin
      CentralFileHeaderSignature:=Signature;
      ZipFileStream.Read(VersionMadeBy,2);
      ZipFileStream.Read(CommonFileHeader,sizeof(CommonFileHeader));
      ZipFileStream.Read(FileCommentLength,2);
      ZipFileStream.Read(DiskNumberStart,2);
      ZipFileStream.Read(InternalFileAttributes,2);
      ZipFileStream.Read(ExternalFileAttributes,4);
      ZipFileStream.Read(RelativeOffsetOfLocalHeader,4);
      SetLength(FileName,CommonFileHeader.FilenameLength);
      ZipFileStream.Read(PChar(FileName)^,CommonFileHeader.FileNameLength);
      SetLength(ExtraField,CommonFileHeader.ExtraFieldLength);
      ZipFileStream.Read(PChar(ExtraField)^,CommonFileHeader.ExtraFieldLength);
      SetLength(FileComment,FileCommentLength);
      ZipFileStream.Read(PChar(FileComment)^,FileCommentLength);
      end;
   end;
  Signature:=0;
  ZipFileStream.Read(Signature,4);
 until Signature<>$02014B50;
 if Signature=$06054B50 then
  begin
   EndOfCentralDirectory.EndOfCentralDirSignature:=Signature;
   ZipFileStream.Read(EndOfCentralDirectory.NumberOfThisDisk,sizeof(EndOfCentralDirectory)-4);
   SetLength(ZipFileComment,EndOfCentralDirectory.ZipfileCommentLength);
   ZipFileStream.Read(PChar(ZipFileComment)^,EndOfCentralDirectory.ZipfileCommentLength);
  end;
end;

procedure TZipFile.LoadFromFile(const FileName:String);
var ZipFileStream:TFileStream;
begin
 ZipFileStream:=TFileStream.Create(FileName,fmOpenRead or fmShareDenyWrite);
 try
  LoadFromStream(ZipFileStream);
 finally
  ZipFileStream.Free;
 end;
end;

procedure TZipFile.WriteFileToStream(Stream:TStream;FileName:String);
var A,B:Integer;
      S:String;
begin
 while (FileName<>'') and ((FileName[1]='/') or (FileName[1]='\')) do Delete(FileName,1,1);
 FileName:=StringReplace(FileName,'\','/',[rfReplaceAll]);
 B:=-1;
 for A:=0 to High(Files) do
  if SameText(Files[A].FileName,FileName) then
   begin
    B:=A;
    break;
   end;
 if B<0 then exit;
 S:=GetUncompressed(B);
 Stream.Write(S[1],length(S));
end;

function TZipFile.GetUncompressed(I:Integer):String;
var    Decompressor:TDecompressionStream;
 UncompressedStream:TStringStream;
            AHeader:String;
          ReadBytes:Integer;
        LoadedCrc32:DWORD;
begin
 if (I<0) or (I>High(Files)) then
  raise Exception.Create('Index out of range.');
 AHeader:=Chr(120)+Chr(156);
 if Files[I].CommonFileHeader.CompressionMethod=0 then //not compressed
  begin
   Result:=Files[I].CompressedData;
  end else
   begin
    UncompressedStream:=TStringStream.Create(AHeader+Files[I].CompressedData);
    try
     Decompressor:=TDecompressionStream.Create(UncompressedStream);
     try
      SetLength(Result,Files[I].CommonFileHeader.UncompressedSize);
      ReadBytes:=Decompressor.Read(PChar(Result)^,Files[I].CommonFileHeader.UncompressedSize);
      if ReadBytes<>Integer(Files[I].CommonFileHeader.UncompressedSize) then Result:='';
     finally
      Decompressor.Free;
     end;
    finally
     UncompressedStream.Free;
    end;
    LoadedCRC32:=ZipCRC32(Result);
    if LoadedCRC32<>Files[I].CommonFileHeader.Crc32 then
     raise EZipFileCRCError.CreateFmt('CRC Error in "%s".',[Files[I].FileName]);
   end;  
end;

procedure TZipFile.SetUncompressed(I:Integer;const Value:String);
var    Compressor:TCompressionStream;
 CompressedStream:TStringStream;
  UseUncompressed:Boolean;
begin
 if I>High(Files) then

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -