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);
}
}