HOME > GZIP
							파일의 구조 > 예제 소스 보기
GZIP 압축 예제 소스 코드
목차
1.   핵심 사항
2.   gzipfile.h
3.   gzipfilc.cpp
1.   복원
					
| int
  main( int argc, char *argv[] ) {         if
  ( argv[1] == NULL )                return
  0;         //원본 파일의 사이즈를 알아낸다.          FILE
  *fp = fopen( argv[1] , "rb" );         fseek(
  fp, 0L, SEEK_END );         int
  orgsize = ftell( fp );         fseek(
  fp, 0L, SEEK_SET );         char
  buffer[4096];         int
  tmpsize = orgsize;         CGZipFile
  gzipFile;                  //압축률을 정한다.         gzipFile.SetCompressLevel(
  Z_DEFAULT_COMPRESSION );         //압축파일을 연다.         gzipFile.Open(
  "gzip.gz", "wb" );         char
  result[ 0x8000 * 2 ];         //헤더 부분을 생성한다.         gzipFile.SetHeader(
  argv[1] );         //압축한다.         gzipFile.DeflateInit(
  result, 0x8000 );         while(
  (tmpsize - 4096 )> 0 )         {                fread(
  buffer, 4096, 1, fp );                gzipFile.Write(
  buffer, 4096 );                tmpsize
  -= 4096;         }         fread(
  buffer, tmpsize, 1, fp );         gzipFile.Write(
  buffer, tmpsize, Z_FINISH );         //Close()함수는 Crc32와 원본 파일의 크기를 기록한다.         gzipFile.Close(
  orgsize );         fclose(
  fp );         return
  1; } //기본 헤더 정보를 위한 구조체이다. typedef
  struct _tagGZIPHEADER {         BYTE
  id[2];         BYTE
  cm;         BYTE
  flag;         BYTE
  mTime[4];         BYTE
  xfl;         BYTE
  os; }GZIPHEADER; void
  CGZipFile::SetHeader( const char *_inputfilename ) {         //ID값은 정해져 있다.         gzipHeader.id[0]
  = 0x1f;         gzipHeader.id[1]
  =0x8b;         //CM값도 정해져 있다.         gzipHeader.cm
  = 8;         // flag=8이면 원본 파일의 이름을 기록한다.         gzipHeader.flag
  = 8;         //현재 시간을 기록한다.         time_t
  mtime;         time(
  &mtime );         memcpy(
  gzipHeader.mTime, &mtime, 4 );         //XFL값 세팅         gzipHeader.xfl
  = 0;         //파일 시스템 기록         gzipHeader.os
  = 0x0b;         //기본헤더 기록         fseek(
  fp, 0, SEEK_SET );         fwrite(
  &gzipHeader, sizeof( gzipHeader ), 1, fp );         //flag=8이므로 원본 파일의 이름도 기록해야 한다.              char
  buffer[ 128 ];         char
  *ptr = (char *)_inputfilename;         while(
  *ptr != '\\' && *ptr != '\0' )         {                ptr++;         }         if
  ( *ptr == '\0' )         {                strcpy(
  buffer, _inputfilename );         }         else         {                ptr++;                strcpy(
  buffer, ptr );         }         int
  len = strlen( buffer );         buffer[
  len ] = 0;         fwrite(
  buffer, len + 1, 1, fp ); } void
  CGZipFile::Close( int _orgsize ) {         deflateEnd(
  &gzipStream );         //CRC32 정보를 기록한다.         fwrite(
  &crc, 4, 1, fp );         //원본파일의 크기를 기록한다.         fwrite(
  &_orgsize, 4, 1, fp );         fclose(fp); } | 
#ifndef         __GZIPFILE_H__
#define        __GZIPFILE_H__
#include               "zlib.h"
#include               "zconf.h"
#ifndef
Z_BUFSIZE
#define
Z_BUFSIZE (16384)
#endif
#ifndef
Z_MAXFILENAMEINZIP
#define
Z_MAXFILENAMEINZIP (256)
#endif
#ifndef
DEF_MEM_LEVEL
#if
MAX_MEM_LEVEL >= 8
#  define DEF_MEM_LEVEL 8
#else
#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
#endif
#endif
typedef        unsigned char          uchar;
typedef        const uchar                   cuchar;
typedef        unsigned long          ulong;
typedef        uchar                         BYTE;
#include               <stdio.h>
#define        DEFLATE        0
#define        INFLATE                1
typedef
struct _tagGZIPHEADER
{
        BYTE
id[2];
        BYTE
cm;
        BYTE
flag;
        BYTE
mTime[4];
        BYTE
xfl;
        BYTE
os;
}GZIPHEADER;
class
CGZipFile
{
public:
        CGZipFile();
        ~CGZipFile();
        inline void
SetHeader( const char
*_filename );
        int Open( const char *_filename, const
char *_mode = "wb" );
        int Write( const char *_data, int
_dataSize, int _flush = Z_NO_FLUSH );
        void Close( int
_orgsize );
        inline void
SetCompressLevel( int _compLevel ){
compressLevel = _compLevel; }
        void DeflateInit( char
*_resultData, int _resultSize );
        
private:
        GZIPHEADER
gzipHeader;
        int fType;
        int compressLevel;
        FILE
*fp;      
        char *result;
        int resultSize;
        int crc;
        int orgsize;
        z_stream
gzipStream;
};
#endif         /* gzipfile.h */ 
////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "gzipfile.h"
#include <string.h> 
#include <time.h> 
CGZipFile::CGZipFile() 
{ 
        fp
= NULL; 
        fType
= DEFLATE; 
        compressLevel
= Z_DEFAULT_COMPRESSION; 
        crc
= crc32( 0L, 0L, 0L ); 
        memset(
&gzipStream, 0, sizeof( gzipStream ) ); 
} 
CGZipFile::~CGZipFile() 
{ 
        if
( fp ) 
        {
                fclose(
fp ); 
                fp =
NULL; 
        }
} 
void CGZipFile::Close( int _orgsize ) 
{ 
        deflateEnd(
&gzipStream ); 
        fwrite(
&crc, 4, 1, fp ); 
        fwrite(
&_orgsize, 4, 1, fp ); 
        fclose(fp);
} 
int CGZipFile::Open( const char *_filename ) 
{ 
        int
err; 
        gzipStream.zalloc
= (alloc_func)0; 
        gzipStream.zfree
= (free_func)0; 
        gzipStream.opaque
= (voidpf)0; 
        fType
= DEFLATE; 
             //주의!!!!!
             //window
bit값이 음수이면 zlib 형식이 아닌 gzip파일 포맷이라는 뜻이다.
        err
= deflateInit2( &gzipStream, compressLevel, Z_DEFLATED, -MAX_WBITS, 
                DEF_MEM_LEVEL,
Z_DEFAULT_STRATEGY ); 
        if
( err != Z_OK ) 
                return
0; 
        fp
= fopen( _filename, "wb" ); 
        return
(int) fp; 
} 
int CGZipFile::Write( const char *_data, int
_dataSize, int _flush ) 
{ 
        int
err; 
        gzipStream.avail_out
= (uInt)this->resultSize; 
        gzipStream.next_out
= (Bytef*)this->result; 
        gzipStream.avail_in
= (uInt)_dataSize; 
        gzipStream.next_in
= (Bytef*)_data; 
        crc
= crc32( crc, (const BYTE *)_data, _dataSize ); 
        err
= ::deflate( &gzipStream, _flush ); 
        if
( err != Z_OK && err != Z_STREAM_END ) 
                return
0; 
        int
writeSize = gzipStream.total_out; 
        if
( writeSize != 0 ) 
        {
                if (
writeSize > DEFLATE_SIZE ) 
                        printf("Big
Size: %d\n", writeSize ); 
                printf("Size:
%d\n", writeSize ); 
                if ( fwrite(
result, writeSize, 1, fp ) == 0 ) 
                        return
Z_ERRNO; 
                gzipStream.total_out
= 0; 
        }
        if
( err != Z_OK && err != Z_STREAM_END ) 
                return
0; 
        return
1; 
} 
void CGZipFile::DeflateInit( char *_resultData ,
int _resultSize ) 
{ 
        result
= _resultData; 
        resultSize
= _resultSize; 
} 
void CGZipFile::SetHeader( const char
*_inputfilename ) 
{ 
        gzipHeader.id[0]
= 0x1f; 
        gzipHeader.id[1]
=0x8b; 
        gzipHeader.cm
= 8; 
        gzipHeader.flag
= 8; 
        time_t
mtime; 
        time(
&mtime ); 
        memcpy(
gzipHeader.mTime, &mtime, 4 ); 
        gzipHeader.xfl
= 0; 
        gzipHeader.os
= 0x0b; 
        fseek(
fp, 0, SEEK_SET ); 
        fwrite(
&gzipHeader, sizeof( gzipHeader ), 1, fp ); 
        char
buffer[ 128 ]; 
        char
*ptr = (char *)_inputfilename; 
        while(
*ptr != '\\' && *ptr != '\0' ) 
        {
                ptr++;
        }
        if
( *ptr == '\0' ) 
        {
                strcpy(
buffer, _inputfilename ); 
        }
        else
        {
                ptr++;
                strcpy(
buffer, ptr ); 
        }
        int
len = strlen( buffer ); 
        buffer[
len ] = 0; 
        fwrite(
buffer, len + 1, 1, fp ); 
        
					
} 
int main( int argc, char *argv[] ) 
{ 
        if
( argv[1] == NULL ) 
                return
0; 
        FILE
*fp = fopen( argv[1] , "rb" ); 
        fseek(
fp, 0L, SEEK_END ); 
        int
orgsize = ftell( fp ); 
        fseek(
fp, 0L, SEEK_SET ); 
        char
buffer[ DEFLATE_SIZE + 1]; 
        int
tmpsize = orgsize; 
        CGZipFile
gzipFile; 
        gzipFile.SetCompressLevel(
Z_DEFAULT_COMPRESSION ); 
        gzipFile.Open(
"gzip.gz" ); 
        char
result[ 0x8000 * 2 ]; 
        gzipFile.SetHeader(
argv[1] ); 
        gzipFile.DeflateInit(
result, 0x8000 ); 
        while(
(tmpsize - DEFLATE_SIZE )> 0 ) 
        {
                fread(
buffer, DEFLATE_SIZE, 1, fp ); 
                gzipFile.Write(
buffer, DEFLATE_SIZE ); 
                tmpsize
-= DEFLATE_SIZE; 
        }
        fread(
buffer, tmpsize, 1, fp ); 
        gzipFile.Write(
buffer, tmpsize, Z_FINISH ); 
        gzipFile.Close(
orgsize ); 
        fclose(
fp ); 
        return
1; 
} 
////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
gz_decompress(const char*
src_filename)        /* 전개(복원) */
{
        z_stream
z;
        unsigned char* inbuf
= NULL;
        unsigned char* outbuf
= NULL;
        char dest_filename[256]={0,};
        unsigned int count,
status;
        unsigned long
INBUFSIZE;
        unsigned long
OUTBUFSIZE;
        
        //파일 네임 설정
        int strl;
        strl
= strlen(src_filename);
        strncpy(dest_filename,src_filename,
strl-4);
        printf("dest
filename = %s\n\n",dest_filename);
        //압축 파일을 읽어들인다.
        FILE*
fin = fopen(src_filename, "rb");
        if(fin == NULL)
        {
               printf("%s
open failed\n", src_filename);
               exit(1);
        }
        FILE*
fout = fopen(dest_filename, "wb");
        if(fout == NULL)
        {
               printf("%s
open failed\n", dest_filename);
               exit(1);
        }
        
        //압축 파일로부터 헤더를 읽어온다.
        GZIPHEADER
header;
        fseek(fin,0,SEEK_SET);
        fread(&header,sizeof(GZIPHEADER),1,fin);
        //압축 파일로부터 원래 파일의 이름을 알아온다.
        char filename[1024]="\0";
        int pos=0;
        char _char=(char)fgetc(fin);
        filename[pos]=_char;
        while(_char!='\0')
        {
               pos++;
               _char=(char)fgetc(fin);
               filename[pos]=_char;
        }
        filename[pos]='\0';
        fprintf(stdout,"source
file name = %s\n\n",filename);
        
        //압축된 파일의 크기를 알아온다.
        fseek(fin,0,SEEK_END);
        unsigned long
compressedSize=ftell(fin) - sizeof(GZIPHEADER) 
               -
( strlen(filename)+1 ) - sizeof(int)*2;
        fprintf(stdout,"compressed
file size = %d\n\n",compressedSize);
        
        //원본 파일의 크기를 알아온다.
unsigned
long orgSize=0;
        fseek(fin,0-sizeof(int),SEEK_END);
        fread(&orgSize,sizeof(int),1,fin);
        fprintf(stdout,"original
file size = %d\n\n",orgSize);
        
        //압축되어 있는 파일을 메모리로 가져온다.
        fseek(fin,+(
sizeof(GZIPHEADER)+(strlen(filename)+1)
),SEEK_SET);
        char *compressedData=new
char[compressedSize];
        fread(compressedData,compressedSize,1,fin);
        
        char *orgData=new char[orgSize];
        orgData[0]='\0';
   
        
        //압축을 하기 위한 환경 설정
        INBUFSIZE=compressedSize;
OUTBUFSIZE=orgSize;
inbuf = (unsigned
char *)malloc(INBUFSIZE);
outbuf = (unsigned
char *)malloc(OUTBUFSIZE);
inbuf=(unsigned
char*)compressedData;
//테스트를 위해 일단 outbuf에 “garbage”라는 문자열을 넣었다.
strcpy((char*)outbuf, "garbage");
        z.zalloc
= Z_NULL;
        z.zfree
= Z_NULL;
        z.opaque = Z_NULL;
        z.next_in 
= inbuf;
        z.avail_in = 0;
        z.next_out = outbuf;
        //GZIP 형식에서는 window bit값이 –MAX_WBITS이다.
int err =
inflateInit2(&z,-(MAX_WBITS));
        //복원한다.
        while (z.total_out
< orgSize && z.total_in < compressedSize) {
               z.avail_in
= z.avail_out = 4096; /* force small buffers */
               err
= inflate(&z, Z_NO_FLUSH);
               if (err == Z_STREAM_END) break;
        
               if (err != Z_OK) {
                       fprintf(stderr,
"inflate error: %d\n", err);
                       exit(1);
               }
        }
        //복원을 끝낸다.
        err = inflateEnd(&z);
        if (err != Z_OK) { 
               fprintf(stderr,
"inflateEnd error: %d\n", err);
               exit(1);
        } 
}