카테고리 없음

[일반/컴포넌트] Zlib 를 이용한 압축과 해제

쇼핑스크래퍼3 2023. 9. 1. 08:39
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Zlib, ComCtrls, DbiTypes, DbiProcs, DbiErrs;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    RichEdit1: TRichEdit;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure CompressStream(inpStream, outStream: TStream);
var
  InpBuf, OutBuf: Pointer;
  InpBytes, OutBytes: Integer;
begin
  InpBuf := nil;
  OutBuf := nil;
  try
    GetMem(InpBuf, inpStream.Size);
    inpStream.Position := 0;
    InpBytes := inpStream.Read(InpBuf^, inpStream.Size);
    CompressBuf(InpBuf, InpBytes, OutBuf, OutBytes);
    outStream.Write(OutBuf^, OutBytes);
  finally
    if InpBuf <> nil then FreeMem(InpBuf);
    if OutBuf <> nil then FreeMem(OutBuf);
  end;
end;

procedure DecompressStream(inpStream, outStream: TStream);
var
  InpBuf, OutBuf: Pointer;
  OutBytes, sz: Integer;
begin
  InpBuf := nil;
  OutBuf := nil;
  sz := inpStream.Size - inpStream.Position;
  if sz > 0 then
    try
      GetMem(InpBuf, sz);
      inpStream.Read(InpBuf^, sz);
      DecompressBuf(InpBuf, sz, 0, OutBuf, OutBytes);
      outStream.Write(OutBuf^, OutBytes);
    finally
      if InpBuf <> nil then FreeMem(InpBuf);
      if OutBuf <> nil then FreeMem(OutBuf);
    end;
  outStream.Position := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ms1, ms2: TMemoryStream;
begin
  ms1 := TMemoryStream.Create;
  try
    ms2 := TMemoryStream.Create;
    try
      RichEdit1.Lines.SaveToFile('C:\zzz\original.dat'); // 원본

      RichEdit1.Lines.SaveToStream(ms1);
      CompressStream(ms1, ms2);
      ShowMessage(Format('압출율: %d %%', [round(100 / ms1.Size * ms2.Size)]));
      ms2.SaveToFile('C:\zzz\compressed.dat');
      RichEdit1.Clear;
    finally
      ms1.Free;
    end;
  finally
    ms2.Free;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  ms1, ms2: TMemoryStream;
begin
  ms1 := TMemoryStream.Create;
  try
    ms2 := TMemoryStream.Create;
    try
      ms1.LoadFromFile('C:\zzz\compressed.dat');
      DecompressStream(ms1, ms2);
      RichEdit1.Lines.LoadFromStream(ms2);
    finally
      ms1.Free;
    end;
  finally
    ms2.Free;
  end;
end;

// 아래는 예제 문자열을 만들기 윈한 것입니다
procedure TForm1.FormCreate(Sender: TObject);
var
  Category: byte;
  Code: byte;
  ResultCode: word;
  ErrorString: array[0..DBIMAXMSGLEN + 1] of char;
  OutString: string;
begin
  // BDE 환경을 초기화 한다
  DbiInit(nil);

  RichEdit1.Lines.Clear;

  for Category := ERRCAT_NONE to ERRCAT_RC do
    for Code := 0 to 255 do
    begin
      ResultCode := (Category shl 8) + Code;
      // error code 에 해당하는 메시지를 구한다
      DbiGetErrorString(ResultCode, ErrorString);
      if StrLen(ErrorString) > 0 then // 주어진 에러코드의 설명이 있는것만 발취
      begin
        OutString := Format('%6d  %0.4x  %s', [ResultCode, ResultCode, ErrorString]);
        RichEdit1.Lines.Add(OutString);
      end;
    end;

  // BDE 로 부터 접속을 해제하여 사용한 자원을 반납한다
  DbiExit;
end;

end.