출처 : http://code.oopman.com/103
zlib를 이용한 zip 압축 기능 구현 테스트 프로그램.
단순 압축 기능만 콘솔 프로그램으로 구현해본 것입니다.
소스는 다음과 같습니다.
/*
* 파일명 : ZipTest.cpp
* 사용법 : ZipTest [filename]
* 압축하고자 하는 filename를 입력하면 filename.zip이라는 압축파일이
* 생성된다.
*/
// 표준 C헤더파일
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// zlib 헤더파일
#include <zlib.h>
int main(int argc, char *argv[])
{
char *filename = NULL;
char *gzfilename = NULL;
gzFile zf;
int n;
char buf[256];
int lerrno;
FILE *fp;
if(argc !=2) {
printf("Usage : ZipTest [file name]\n");
exit(0);
}
filename = argv[1];
// 압축파일의 이름은 filename.zip 으로 한다.
gzfilename = (char *)malloc(strlen(filename)*sizeof(char));
sprintf(gzfilename, "%s.zip", filename);
if ((fp = fopen(filename, "rb")) == NULL) {
printf("file open error\n");
exit(0);
}
// 압축파일을 연다.
if ((zf = gzopen(gzfilename, "wb")) == NULL) {
exit(0);
}
// 원본파일을 에서 데이타를 읽어들이고
// gzwrite함수를 이용해서 데이터를 압축하고 파일에 쓴다.
while((n = fread(buf, sizeof(char), 255, fp)) > 0)
{
if (gzwrite(zf, buf, n) < 0) {
printf("%s\n",gzerror(zf, &lerrno));
exit(0);
}
}
gzclose(zf);
printf("compression completed : %s => %s\n", filename, gzfilename);
return 0;
}
앞서 만든 ZipTest로 만든 압축 프로그램을 풀어주는 UnzipTest 입니다.
역시 기능 구현 테스트만을 위해 간단히 콘솔 프로그램으로 만들었고 zlib를 이용했습니다..
소스는 다음과 같습니다.
// UnzipTest.cpp : Defines the entry point for the console application.
#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>
#define BUF_SIZE 1024
int main(int argc, char* argv[])
{
char *srcFileName, *destFileName;
gzFile zfSrc;
FILE *fpDest;
char buf[BUF_SIZE];
int gzr;
// 파라미터가 맞지 않으면 종료
if(argc != 3) {
printf("Usage: UnzipTest [source filename] [destination filename]");
exit(0);
}
srcFileName = argv[1];
destFileName = argv[2];
// 파일이 존재하지 않으면 종료
if((zfSrc = gzopen(srcFileName, "rb")) == NULL) {
printf("can't open source file");
exit(0);
}
// destination 파일 열기
if((fpDest = fopen(destFileName, "wb")) == NULL) {
gzclose(zfSrc);
printf("can't create destination file");
exit(0);
}
// 압축 풀기
while((gzr = gzread(zfSrc, buf, BUF_SIZE)) > 0) {
fwrite(buf, sizeof(char), gzr, fpDest);
}
gzclose(zfSrc);
fclose(fpDest);
// 에러발생시 종료
if(gzr < 0) {
printf("Error occured.");
exit(0);
}
printf("Decompression completed.");
return 0;
}
일단 기본적인 압축 및 압축 푸는 기능은 구현할 수 있게 되었습니다. 하지만 여러 파일(폴더 포함)을 하나의 압축파일로 묶어서 압축하는 건 어떻게 해야 할지 아직까지는 모르겠군요. 좀더 연구를 해보야야겠습니다.
앞서 만든 두개의 ZipTest, UnzipTest 프로그램은 zip 압축 프로그램이 아니라 gz 압축 프로그램이었다. 첨엔 zlib가 zip 압축을 위한 라이브러리인줄 알았으나 사실은 gz 압축용 라이브러리였던 것이다. 이런..
(혹시 믿고 따라하신 분이 계셨다면 정말로 사과의 말씀드립니다. 사실 저도 몰랐답니다. ㅠㅠ)
그렇다면 zlib는 zip 압축을 지원하지 않는가? http://zlib.net 의 FAQ에서는 다음과 같이 대답해주고 있다.
Can zlib handle .zip archives?
Not by itself, no. See the directory contrib/minizip in the zlib distribution.
Not by itself 라니, 이 무슨 애매모호한 대답인가. -_-; 하지만 이 대답과 기타 여러 정황(?)으로 볼때 zip과 gz은 전혀 상관 없는 것도 아니라는 것이다. http://www.winimage.com/zLibDll/unzip.html 를 보면 이런 말이 나온다.
Using Unzip package
The Unzip source is only two file : unzip.h and unzip.c. But it use the Zlib files.
miniunz.c is a very simple, but real unzip program (display file in zipfile or extract them).
Using Zip package
The Zip source is only two file : zip.h and zip.c. But it use the Zlib files.
minizip.c is a very simple, but real zip program.
zip과 unzip 기능을 해주는 소스는 내부적으로 zlib를 이용한다고 한다. 이런 추리가 가능하다. gz은 단순 파일 압축이며, zip은 zlib 등의 gz 압축 알고리즘을 이용하되 이를 다수의 파일 및 폴더에 대한 압축이 가능하도록 만든 것이다라는.. 물론 틀린 추론일 수도 있다. -.-;
하지만 분명한 것은 Gilles Vollant가 만든 minizip의 네개의 소스 zip.h, zip.c, unzip.h, unzip.c를 이용하면 zip 압축 기능의 구현이 가능할 것이라는 사실이다.
헌데 여기서 한가지 문제가 있다. zip.c, unzip.c 라는 파일명을 보아도 알수 있지만 이것은 C++이 아닌 C로 쓰여진 프로그램이라는 것이다. 물론 VC++에서 C 컴파일이 가능하지만, 이를 C++로 래핑(wrapping)해 놓은 소스가 있다.
http://www.codeproject.com/cpp/zipunzip.asp 이곳에서 얻을 수 있을 것이다. Win32 Wrapper classes for Gilles Volant's Zip/Unzip API 라는 제목의 Zip/Unzip API란 바로 위에서 소개한 zip.h, unzip.h에서 찾을 수 있는 API들일 것이다. 이것을 Daniel Godson이라는 사람이 친절하게도 Win32 버전으로 래핑해놓은 것이다.
Win32 Wrapper classes for Gilles Volant's Zip/Unzip API 의 클래스 CZipper CUnzipper의 public 메소드 원형입니다.
class CZipper
{
public:
CZipper(LPCTSTR szFilePath = NULL, LPCTSTR szRootFolder = NULL, bool bAppend = FALSE);
virtual ~CZipper();
// simple interface
static bool ZipFile(LPCTSTR szFilePath); // saves as same name with .zip
static bool ZipFolder(LPCTSTR szFilePath, bool bIgnoreFilePath); // saves as same name with .zip
// works with prior opened zip
bool AddFileToZip(LPCTSTR szFilePath, bool bIgnoreFilePath = FALSE);
bool AddFileToZip(LPCTSTR szFilePath, LPCTSTR szRelFolderPath); // replaces path info from szFilePath with szFolder
bool AddFolderToZip(LPCTSTR szFolderPath, bool bIgnoreFilePath = FALSE);
// extended interface
bool OpenZip(LPCTSTR szFilePath, LPCTSTR szRootFolder = NULL, bool bAppend = FALSE);
bool CloseZip(); // for multiple reuse
void GetFileInfo(Z_FileInfo& info);
};
class CUnzipper
{
public:
CUnzipper(LPCTSTR szFilePath = NULL);
virtual ~CUnzipper();
// simple interface
static bool Unzip(LPCTSTR szFileName, LPCTSTR szFolder = NULL, bool bIgnoreFilePath = FALSE);
// works with prior opened zip
bool Unzip(bool bIgnoreFilePath = FALSE); // unzips to output folder or sub folder with zip name
bool UnzipTo(LPCTSTR szFolder, bool bIgnoreFilePath = FALSE); // unzips to specified folder
// extended interface
bool OpenZip(LPCTSTR szFilePath);
bool CloseZip(); // for multiple reuse
bool SetOutputFolder(LPCTSTR szFolder); // will try to create
// unzip by file index
int GetFileCount();
bool GetFileInfo(int nFile, UZ_FileInfo& info);
bool UnzipFile(int nFile, LPCTSTR szFolder = NULL, bool bIgnoreFilePath = FALSE);
// unzip current file
bool GotoFirstFile(LPCTSTR szExt = NULL);
bool GotoNextFile(LPCTSTR szExt = NULL);
bool GetFileInfo(UZ_FileInfo& info);
bool UnzipFile(LPCTSTR szFolder = NULL, bool bIgnoreFilePath = FALSE);
// helpers
bool GotoFile(LPCTSTR szFileName, bool bIgnoreFilePath = TRUE);
bool GotoFile(int nFile);
};
CZipper 에 대해서는 약간의 추가 설명을 찾을수 있었습니다.
출처 http://www.codeproject.com/cpp/zipunzip.asp
The CZipper class interface provides two approaches to zipping:
1. For simple file and folder zipping, you can use the static ZipFile(...) or ZipFolder(...) methods.
2. For more complex zipping requirements, you can alternatively instantiate a CZipper object, then use OpenZip(...), followed by one or more AddFileToZip(...) or AddFolderToZip(...) calls, before ending with CloseZip().
CZipper 클래스 인터페이스는 zip 압축에 대한 방법을 제공한다.
1. 한개의 파일이나 폴더 압축을 하려면, 정적 메소드 ZipFile(...)과 ZipFolder(...)를 사용하면 된다.
2. 좀더 복잡한 zip 압축을 하고 싶다면, CZipper의 인스턴스를 생성한 후, OpenZip(...)을 호출하고, AddFileToZip(...)이나 AddFolderToZip(...)를 사용하여 파일이나 폴더를 추가하고, CloseZip()으로 마무리한다.
zip 통합 라이브러리를 만들었습니다.
http://zlib.net 의 zlib,
Gilles Volant 의 Zip/Unzip API,
Daniel Godson 의 Win32 Wrapper 클래스를 모두 모아 컴파일하여 통합 라이브러리로 만들었습니다.
각각의 API 에 해당하는 헤더 파일은 관련 사이트에서 소스를 받으시면 함께 받으실 수 있을 겁니다. 윈도우에서의 간단한 zip 압축 구현을 위해서라면 Daniel Godson 의 소스중 Zipper.h, Unzipper.h 만 있어도 될 것입니다.
앞에서 만든 zip 통합 라이브러리 zipunzip.lib를 이용한 zip 압축 프로그램입니다.
역시 기능 구현 테스트를 위하여 간단히 콘솔 프로그램으로 만들었습니다.
소스는 다음과 같습니다.
// SimpleZip.cpp : Defines the entry point for the console application.
// Usage: SimpleZip [flag] [source file]
// flag: c - compress
// d - decompress
#include <stdio.h>
#include <windows.h>
#include <zipper.h>
#include <unzipper.h>
int main(int argc, char* argv[])
{
char *srcFileName;
bool bSrcIsDirectory, br;
DWORD fileAttr;
// 파라미터 확인
if(argc != 3) {
printf("Usage: SimpleZip [flag] [source file]\n");
printf(" flag: c - compress\n");
printf(" d - decompress");
exit(0);
}
srcFileName = argv[2];
// 소스 파일 확인
bSrcIsDirectory = ((fileAttr = GetFileAttributes(srcFileName)) & FILE_ATTRIBUTE_DIRECTORY) > 0;
if(fileAttr == 0xFFFFFFFF) {
printf("file not exist or has unknown problems");
exit(0);
}
switch(argv[1][0]) {
case 'c':
case 'C':
// 디렉토리인 경우
if(bSrcIsDirectory) {
br = CZipper::ZipFolder(srcFileName, FALSE);
}
// 파일인 경우
else {
br = CZipper::ZipFile(srcFileName);
}
printf(br ? "compression completed." : "error occured.");
break;
case 'd':
case 'D':
// 디렉토리인 경우
if(bSrcIsDirectory) {
printf("%s isn't a file", srcFileName);
exit(0);
}
// 파일인 경우
else {
CUnzipper uz;
br = uz.OpenZip(srcFileName);
if(br) br = uz.UnzipTo(".");
printf(br ? "decompression completed." : "error occured.");
}
break;
default:
printf("wrong flag.");
break;
}
return 0;
}
'소프트웨어' 카테고리의 다른 글
Ctags 설정 및 사용법 (0) | 2014.02.21 |
---|---|
[펌] zlib를 사용법 (2) | 2014.02.20 |
[zlib] deflate algorithm에 대해서 (0) | 2014.02.18 |
[zlib] zlib에 대해서 (1) (0) | 2014.02.18 |
[c++] pointer로 선언 후에 pointer를 그대로 넘겨서 pointer에 담아 사용하기 (0) | 2014.02.14 |