2005/01/10 11:35 http://blog.naver.com/pacho7/9145867 |
[강좌] ZLIB 사용하기 | |
ZLIB 사용하기 저자: 조호석 ( laday@chollian.net ) 이글은 자유롭게 배포하실 수 있습니다만, 반드시 출처를 밝혀주시기 바랍니 다. 편의상 존칭은 생략합니다. ----------------------------------------------------------------------- 1. ZLIB이란? ----------------------------------------------------------------------- 파일 압축 알고리즘중 하나로, LZW방식과 같이 가장 널리 쓰이는 방식중 하나 이다. 이전까지만 해도 LZW (LHA라는 프로그램이 이 방식을 사용함)가 많이 사용되었던 것이 사실이지만, ZLIB이 공개되면서 지금은 이 알고리즘이 많이 사용되고 있다. 누구나 자유롭게 사용할 수 있다. ZLIB은 안정성이 입증되어있다. 안정성이란 압축한 다음 반드시 정상적으로 풀린다는 것을 보증하는 것이며 다시 같은 방식으로 압축을 시도했을 때 더이 상 압축되지 않는것을 의미한다. [당연한거 아니냐]라 할지 몰라도, 그렇지 못한 경우가 많다. 내 기억으론, 초창기 RAR방식도 이 안정성이 떨어져서 고 전을 면치 못했다. 안정성이 입증된 관계로 많은 ZIP파일 아류작들, 대표적인 것이 CAB이란 파일(윈도우 인스톨본에 쓰이는 압축 파일), 이 생겨났다. 필 자도 LZ라 하여 하나 만들어서 사용하고 있다. 재미있는 건 1.1.3버전의 ZLIB는 잘 사용되지 않는다고 한다. (어디서 들은 이야기다. No Warranty) 1.1.2버전이 주로 사용된다고 하는데, 필자의 경우는 그냥 1.1.3을 사용하였다. 남이 뭐라 해도 내가 보기엔 사용에 별 문제를 발 견하지 못했다. 어디에 쓰나? 데이터 압축 알고리즘을 어디에 쓰는지는 글쎄... 잘 모르겠다. .. ^^; 어쨌든 이 알고리즘은 그대로 ZIP파일에 사용된다. 따라서 ZIP과 같은 포맷을 독자적으로 개발하거나, 파일 송 수신 프로토콜과 같은 경우, 그리고 암호화 까지는 되지 않아도 텍스트를 TCP를 통해 그냥 전송하긴 싫을 때 사 용하면 된다. (특히 나같은 사람은 그냥 전송하는건 무쟈게 싫어한다. 별거 아닌 데이터지만, 뭔가 걸리는게 있어서...) ----------------------------------------------------------------------- 2. 준비 ----------------------------------------------------------------------- ZLIB를 다운받자. 이곳 자료실에도 올려놓았지만 혹시모르니 URL을 적는다 http://www.base2ti.com 델파이5용 ZLIB http://www.info-zip.org/pub/infozip/zlib/ ZLIB 공식 홈페이지 다운로드 한 후 적당한 곳에 압축을 풀자. File -> New Application을 선택한다. Project -> Add to Project를 선택해 ZLIB.PAS라는 파일을 추가한다. 이로써 ZLIB를 사용할 준비가 끝났다. ----------------------------------------------------------------------- 3. 압축 하기 ----------------------------------------------------------------------- 이 라이브러리는 모두 스트림을 이용하는 방식으로 되어 있다. 이렇게 하면 많은 곳에 쉽게 응용이 가능하기 때문이다. 물론 속도는 조금 느리겠지만... 이 방식이 정석은 아니니, 다른 방식을 생각해 보는 것도 좋을 것이다. 압축을 하기위한 함수 CompressStream을 생각해 보자. 먼저 입력으로 받을 스 트림과 출력할 스트림, 그리고 압축한 상태를 보여주는 이벤트 핸들러가 필요 할 것이다. 따라서 프로토타입은 다음과 같은 형태를 보이게 된다. function CompressStream(Stream: TStream; OutStream: TStream; OnProgress: TNotifyEvent): boolean; 이제 내부코드를 생각해 보자. TZCompressionStream 이란 객체에서 압축과 관 련된 작업을 할 수 있게 되었다. 일단 이 객체를 생성시킨 후, 이벤트 핸들러 를 정해 준후, 데이터를 넣어주면 모든 것은 해결된다. 이 부분은 다음과 같 은 간단한 코드로 완성된다. function CompressStream(Stream: TStream; OutStream: TStream; OnProgress: TNotifyEvent): boolean; var CS: TZCompressionStream; begin CS := TZCompressionStream.Create(OutStream, zcMax); // 스트림 생성 try if Assigned(OnProgress) then CS.OnProgress := onProgress; CS.CopyFrom(Stream, Stream.Size); // 여기서 압축이 진행됨 // 테스트 결과 압축완료시 이벤트가 발생하지 않기 때문에 // 완료시 한번 더 이벤트를 불러준다. if Assigned(OnProgress) then onProgress(CS); Result := True; finally CS.Free; end; end; **************************************************************사용 방법 TForm1에 CompProgressBar: TProgressBar; 를 추가한다. (TProgressBar 컴포 넌트를 폼위에 놓고 이름을 CompProgressBar라고 변경한다) procedure TForm1.OnCompProgress(Sender: TObject); begin CompProgressBar.Position := (Sender as TZCompressionStream).Position; end; procedure TForm1.CompressExecute(Sender: TObject); var Stream, OutStream: TFileStream; FN: string; begin FN := 'C:\TEST.DAT'; Stream := TFileStream.Create(FN, fmOpenRead); OutStream := TFileStream.Create(FN + '.zlib', fmCreate); try CompProgressBar.Max := Stream.Size; CompressStream(Stream, OutStream, onCompProgress); finally OutStream.Free; Stream.Free; end; end; ----------------------------------------------------------------------- 4. 압축 풀기 ----------------------------------------------------------------------- 필자가 가장 애먹었던 부분이었다. 자꾸에러가 나는 부분이라서 어떻게 해야 할지 많이 헤메었었다. 시간에 쫒기는 바람에 처음 코드는 그냥 원시적으로 해결했지만, 지금은 많이 해결되었다. 이 코드가 정석은 아니라고 생각하니 의견 있는 사람은 이 아이디로 연락주기 바란다. 출력을 위한 함수 DeCompressStream을 생각해 보면 이전에 만든 CompressStre am과 다를 것이 없다는 생각이 들 것이다. function DeCompressStream(Stream: TStream; OutStream: TStream; OnProgress: TNotifyEvent): boolean; 안의 코드는 다음과 같다 function DeCompressStream(Stream: TStream; OutStream: TStream; OnProgress: TNotifyEvent): boolean; const BuffSize = 65535; // 버퍼 사이즈 var DS: TZDeCompressionStream; Buff: PChar; // 임시 버퍼 ReadSize: integer; // 읽은 크기 begin if Stream = OutStream then // 입력 스트림과 출력스트림이 같으면 문제가 발생한다 raise Exception.Create('입력 스트림과 출력 스트림이 같습니다'); Stream.Position := 0; // 스트림 커서 초기화 OutStream.Position := 0; //인풋 스트림을 옵션으로 객체 생성. DS := TZDeCompressionStream.Create(Stream); try if Assigned(OnProgress) then DS.OnProgress := onProgress; GetMem(Buff, BuffSize); try // 버퍼 사이즈만큼 읽어온다. Read함수를 부르면 압축이 풀리게 된다. repeat ReadSize := DS.Read(Buff^, BuffSize); if ReadSize <> 0 then OutStream.Write(Buff^, ReadSize); until ReadSize < BuffSize; if Assigned(OnProgress) then onProgress(DS); //Compress와 같은이유 Result := True; finally FreeMem(Buff) end; finally DS.Free; end; end; ************************************************************** 사용방법 TForm1에 DeCompProgressBar: TProgressBar; 를 추가한다. (TProgressBar 컴 포넌트를 폼위에 놓고 이름을 DeCompProgressBar라고 변경한다) procedure TForm1.OnDeCompProgress(Sender: TObject); begin DeCompProgressBar.Position:=(Sender as TZDeCompressionStream).Position; end; procedure TForm1.DoDeComp(FN: string); var Stream, OutStream: TFileStream; Cursor: TCursor; begin FN := 'C:\TEST.DAT.ZLIB'; Stream := TFileStream.Create(FN, fmOpenRead) OutStream := TFileStream.Create(ChangeFileExt(FN, ''), fmCreate); try DeCompProgressBar.Max := Stream.Size; DeCompressStream(Stream, OutStream, onDeCompProgress); finally OutStream.Free; Stream.Free; end; end; ----------------------------------------------------------------------- 5. 후기 ----------------------------------------------------------------------- 도움이 되었는지 모르겠다. 좋은 라이브러리가 있는데 사용방법이 없는거 같 아 한번 올려 보았다. 아는 사람들에겐 별 필요 없는 글이 되겠지만 나같이 모르는 델피언에겐 많은 도움이 되었을 것으로 믿는다. 이 글에 의견 있다면 이곳 질문 답변란에 질문을 하거나 인터넷 메일, laday@chollian.net 로 연락주기 바란다. [출처] [펌] [강좌] ZLIB 사용하기|작성자 pacho7 |
'델파이 > 델파이관련' 카테고리의 다른 글
델파이로 Shortcut 만들기 (0) | 2012.02.09 |
---|---|
IdFTP 사용 (0) | 2012.02.09 |
RichEdit Message Interface (0) | 2011.09.28 |
Delphi Memo 에서 현재 Line 과 Column 알아내기 (0) | 2011.09.28 |
델파이 함수 이름 문자로 함수 호출하기 (0) | 2011.05.04 |