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

📄 scizipfile.pas

📁 可以压缩和解压一个文件夹(里面有多个文件)或者一个文件!
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit SciZipFile;
// Copyright 2004 Patrik Spanel
// scilib@sendme.cz

// Written from scratch using InfoZip PKZip file specification application note

// ftp://ftp.info-zip.org/pub/infozip/doc/appnote-iz-latest.zip

// uses the Borland out of the box zlib

// Nick Naimo <nick@naimo.com> added support for folders on 6/29/2004 (see "NJN")
// Marcin Wojda <Marcin@sacer.com.pl> added exceptions and try finally blocks

interface

uses SysUtils, Classes, Types, zlib, Windows;

type

  TCommonFileHeader = packed record
    VersionNeededToExtract: WORD; //       2 bytes
    GeneralPurposeBitFlag: WORD; //        2 bytes
    CompressionMethod: WORD; //              2 bytes
    LastModFileTimeDate: DWORD; //             4 bytes
    Crc32: DWORD; //                          4 bytes
    CompressedSize: DWORD; //                 4 bytes
    UncompressedSize: DWORD; //               4 bytes
    FilenameLength: WORD; //                 2 bytes
    ExtraFieldLength: WORD; //              2 bytes
  end;

  TLocalFile = packed record
    LocalFileHeaderSignature: DWORD; //     4 bytes  (0x04034b50)
    CommonFileHeader: TCommonFileHeader; //
    filename: AnsiString; //variable size
    extrafield: AnsiString; //variable size
    CompressedData: AnsiString; //variable size
  end;

  TFileHeader = packed record
    CentralFileHeaderSignature: DWORD; //   4 bytes  (0x02014b50)
    VersionMadeBy: WORD; //                 2 bytes
    CommonFileHeader: TCommonFileHeader; //
    FileCommentLength: WORD; //             2 bytes
    DiskNumberStart: WORD; //               2 bytes
    InternalFileAttributes: WORD; //        2 bytes
    ExternalFileAttributes: DWORD; //        4 bytes
    RelativeOffsetOfLocalHeader: DWORD; // 4 bytes
    filename: AnsiString; //variable size
    extrafield: AnsiString; //variable size
    fileComment: AnsiString; //variable size
  end;

  TEndOfCentralDir = packed record
    EndOfCentralDirSignature: DWORD; //    4 bytes  (0x06054b50)
    NumberOfThisDisk: WORD; //             2 bytes
    NumberOfTheDiskWithTheStart: WORD; //  2 bytes
    TotalNumberOfEntriesOnThisDisk: WORD; //    2 bytes
    TotalNumberOfEntries: WORD; //            2 bytes
    SizeOfTheCentralDirectory: DWORD; //   4 bytes
    OffsetOfStartOfCentralDirectory: DWORD; // 4 bytes
    ZipfileCommentLength: WORD; //          2 bytes
  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
    property Count:integer read GetCount;
    procedure AddFile(const name: string; FAttribute: DWord=0);
    procedure SaveToFile(const filename: string);
    procedure LoadFromFile(const filename: string);
    property Uncompressed[i: integer]: string read GetUncompressed write
    SetUncompressed;
    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;

  EZipFileCRCError = class(Exception);

function ZipCRC32(const Data:string):  longword;

implementation



{ TZipFile }

procedure TZipFile.SaveToFile(const filename: string);
var
  ZipFileStream: TFileStream;
  i: integer;
begin
  ZipFileStream := TFileStream.Create(filename, fmCreate);
  try
    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));
  finally
    ZipFileStream.Free;
  end;

end;

procedure TZipFile.LoadFromFile(const filename: string);
var
  ZipFileStream: TFileStream;
  n: integer;
  signature: DWORD;
begin
  ZipFileStream := TFileStream.Create(filename, fmOpenRead or fmShareDenyWrite);
  n := 0;
  try
    repeat
      signature := 0;
      ZipFileStream.Read(signature, 4);
    until signature = $04034B50;
    repeat
      begin
        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);
            SetLength(extrafield, CommonFileHeader.ExtraFieldLength);
            ZipFileStream.Read(PChar(extrafield)^,
              CommonFileHeader.ExtraFieldLength);
            SetLength(CompressedData, CommonFileHeader.CompressedSize);
            ZipFileStream.Read(PChar(CompressedData)^,
              CommonFileHeader.CompressedSize);
          end;
        end;
      end;
      signature := 0;
      ZipFileStream.Read(signature, 4);
    until signature <> ($04034B50);

    n := 0;
    repeat
      begin
        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);

⌨️ 快捷键说明

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