- 차례
- 1. 소개
- 2. Zlib를 이용한 압축 프로그래밍
-
- 2.1. 유틸리티 함수설명
-
- 2.1.1. compress
- 2.1.2. compress2
- 2.1.3. uncompress
- 2.1.4. gzopen
- 2.1.5. gzdopen
- 2.1.6. gzsetparams
- 2.1.7. gzread
- 2.1.8. gzwrite
- 2.1.9. int VAgzprintf
- 2.1.10. gzputs
- 2.1.11. gzgets
- 2.1.12. gzputc
- 2.1.13. gzgetc
- 2.1.14. gzfluseh
- 2.1.15. gzseek
- 2.1.16. gzrewind
- 2.1.17. gzeof
- 2.1.18. gzclose
- 2.1.19. gzerror
- 2.1.20. zlibVersion
- 2.2. 예제
- 2.3. 네트워크 애플리케이션에서의 활용
1. 소개
PC와 인터넷의 보급으로 데이터의 양이 급증하고 있다. 그러다 보니 데이터 저장공간에 많은 압박을 받게 된다. 거기에 더불어 인터넷이 대중화 되면서 데이터를 전송하기 위한 네트워크자원에의 압박도 받게 되었다.
이런 문제를 해결하기 위해서 개발된게 데이터 압축기술이며, Zlib는 범용적인 데이터의 압축을 위한 목적으로 개발되었다. 이 문서는 Zlib를 설명하기 위한 목적으로 작성되었으며, 레퍼런스 용도로써 유용하게 사용가능 할것이다. 또한 문서의 마지막에 간단한 활용예제를 둠으로써 좀더 쉽게 이해하도록 배려하고 있다.
이 문서의 많은 내용들은 Zlib레퍼런스 메뉴얼을 참고 하고 있다.
2. Zlib를 이용한 압축 프로그래밍
이번장에서는 Zlib에 대한 개략적인 소개와 함께 Zlib에서 제공하는 각종 함수에 대해서 다루게 된다. 그러나 모든 함수들에 대해서는 다루지 않고 프로그래밍 하는데 필요한 필수 함수들만을 다룰 것이다. 이외에도 zlib에서 제공되는 함수들이 있는데, 일반적인 응용 애플리케이션의 제작에는 거의 사용되지 않는 함수들이다. 이들 함수들에 대한 자세한 설명은 Zlib레퍼런스 메뉴얼를 참고하기 바란다.
지금은 단지 자주 사용되는 유틸리티 함수들만 설명하고 있는데, 시간이 된다면 zlib에서 제공하는 다른 함수들에 대해서도 설명하도록 하겠다. (zlib에서는 크게 유틸리티 함수, 기본 함수, 고급 함수 세개로 분류되어서 설명하고 있다.)
2.1. 유틸리티 함수설명
유틸리티 함수들은 말 그대로 응용 애플리케이션 레벨에서 간단하게 사용할 수 있는 높은 수준의 함수들로써 다음장에 설명하게될 기본함수들의 응용함수들이다.
높은 수준의 함수들인 만큼 사용하기 편하고 대부분의 압축작업을 하는데 있어서 여기에서 제공하는 것들로 충분할 것이다.
함수들을 살펴보면 알겠지만 파일관련 작업을 위해 사용되는 함수들과 이름이나 쓰임새가 매우 비슷하다는걸 알 수 있을 것이다. 기존의 표준적인 함수들과 비슷한 인터페이스를 유지하므로써 함수를 이해하고 사용하기가 좀더 수월하다.
2.1.1. compress
int compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); |
compress는 성공적으로 압축되었을 경우 Z_OK를 메모리가 충분하지 않을경우 Z_MEM_ERROR, 버퍼의 크기가 충분하지 않을경우 Z_BUF_ERROR를 리턴한다.
2.1.2. compress2
int compress2(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level); |
리턴값은 commpress와 완전히 동일함으로 참고하기 바란다.
2.1.3. uncompress
int uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); |
성공적으로 수행되었을 경우 Z_OK가 리턴되며, 메모리가 충분치 않을경우 Z_MEM_ERROR, 버퍼의 크기가 충분치 않을 경우 Z_BUF_ERROR, 압축데이터가 잘못되어 있을 경우 Z_DATA_ERROR을 리턴한다.
2.1.4. gzopen
typedef voidp gzFile; gzFile gzopen(const char *path, const char *mode); |
파일을 열기에 실패했을 경우 NULL을 리턴한다.
2.1.5. gzdopen
gzFile gzdopen(int fd, const char *mode); |
실패했을 경우 NULL을 리턴한다.
2.1.6. gzsetparams
int gzsetparams(gzFile file, int level, int strategy); |
압축정책은 Z_DEFAULT_STRATEGY와 Z_FILTERED, Z_HUFFMAN_ONLY 중 하나를 선택할 수 있다.
성공했을 경우 Z_OK를 실패했을 경우 Z_STREAM_ERROR을 리턴한다.
2.1.7. gzread
int gzread(gzFile file, voidp buf, unsigned len); |
성공했을 경우 압축풀린 데이터의 크기를 되돌려준다. 파일의 끝일 경우 0을 그밖의 에러에 대해서는 -1을 리턴한다.
2.1.8. gzwrite
int gzwrite (gzFile file, const voidp buf, unsigned len); |
2.1.9. int VAgzprintf
int VAgzprintf(gzFile file, const char *format, ...); |
2.1.10. gzputs
int gzputs(gzFile file, const char *s); |
성공했을 경우 문자열의 크기를 그렇지 않을 경우 -1을 리턴한다.
2.1.11. gzgets
char *gzgets(gzFile file, char *buf, int len); |
실패 했을경우 Z_NULL을 리턴한다.
2.1.12. gzputc
int gzputc(gzFile file, int c); |
2.1.13. gzgetc
int gzgetc(gzFile file); |
2.1.15. gzseek
z_off_t gzseek(gzFile file, z_off_t offset, int whence); |
이 함수는 압축된 파일내에서 위치이동을 하는게 아닌 압축이 풀린 데이터내에서의 위치이동을 하게 되므로, 파일이 읽기 위해서 열려 있는 경우 극도로 느리게 작동할 것이다. 만약 파일이 쓰기 위해서 열려 있다면 단지 전방향 이동(forward seek)만 허용 된다.
성공했을 경우 압축이 풀린 데이터의 시작지점에서의 변위값을 되돌려주고 실패 했을경우 -1을 리턴한다.
2.1.16. gzrewind
int gzrewind(gzFile file); |
2.1.18. gzclose
int gzclose(gzFile file); |
2.1.19. gzerror
const char * gzerror(gzFile file, int *errnum); |
2.1.20. zlibVersion
const char *zlibVersion(void); |
다음과 같은 방법으로 버젼호환여부를 체크할 수 있을 것이다.
... if (strncmp(zlibVersion(), ZLIB_VERSION, 1) != 0) { printf("Version error\n"); exit(1); } ... |
2.2. 예제
2개의 예제파일을 준비했다. 하나는 특정파일을 압축하는 프로그램이고 또다른 하나는 압축된 파일의 원문 내용을 출력하는 프로그램이다. 매우 간단한 소스 이므로 설명은 주석으로 대신하도록 하겠다.
2.2.1. 파일 압축 예제
예제 : jzip.c
/* * 파일명 : jzip.c * 사용법 : # jzip [filename] * 압축하고자 하는 filename를 입력하면 filename.gz이라는 압축파일이 * 생성된다. */ // zlib 헤더파일 #include <zlib.h> // 표준 C헤더파일 #include <stdio.h> #include <fcntl.h> int main(int argc, char **argv) { char *filename = NULL; char *gzfilename = NULL; gzFile *zfp; int fd; int n; char buf[256]; int lerrno; if(argc !=2) { printf("Usage : jzip [file name]\n"); exit(0); } filename = argv[1]; // 압축파일의 이름은 filename.gz 으로 한다. gzfilename = (char *)malloc(strlen(filename)*sizeof(char)); sprintf(gzfilename, "%s.gz", filename); // 압축원본 파일이 존재하는지 확인한다. if (access(filename, F_OK) != 0) { printf("존재하지 않는 파일입니다\n"); exit(0); } if ((fd = open(filename, O_RDONLY)) < 0) { printf("file open error\n"); exit(0); } // 압축파일을 연다. if ((zfp = gzopen(gzfilename, "wb")) == NULL) { exit(0); } // 원본파일을 에서 데이타를 읽어들이고 // gzwrite함수를 이용해서 데이터를 압축하고 파일에 쓴다. while((n = read(fd, buf, 255)) > 0) { if (gzwrite(zfp, buf, n) < 0) { printf("%s\n",gzerror(zfp, &lerrno)); exit(0); } } gzclose(zfp); printf("압축 성공 : %s => %s\n", filename, gzfilename); } |
# gcc -o jzip jzip.c -lz |
2.2.2. 압축 해제 예제
이번 프로그램은 압축된 text문서의 원래 내용을 보여주는 간단한 프로그램이다.
예제 : jcat.c
#include <zlib.h> #include <stdio.h> int main(int argc, char **argv) { char *filename = NULL; gzFile *zfp; char buf[1024]; if (argc != 2) { printf("Usage : jcat [file name]\n"); exit(0); } filename = argv[1]; if ((zfp = gzopen(filename, "rb")) == NULL) { exit(0); } while(gzgets(zfp, buf, 1023) != NULL) { printf("%s", buf); } gzclose(zfp); } |
2.3. 네트워크 애플리케이션에서의 활용
zlib는 일반 파일을 압축하기 위한 용도로 매우 훌륭한 도구이긴 하지만 인터넷을 통해 대량의 정보를 보내는 요즘에는 특히 네트워크에서의 데이터 압축을 위해서도 중요하게 사용된다.
대부분의 웹서버와 웹클라이언트는 zlib를 이용해서 자체적으로 필요한 데이터를 압축하고 해제하면서 가능한한 네트워크의 자원을 효율적으로 사용할 수 있도록 작성되어지고 있다. 공용으로 사용되는 네트워크 보다는 아무래도 개인이 사용하는 PC의 (CPU)자원을 활용하는게 여러모로 효율적이기 때문이다.
네트워크 애플리케이션에서 데이터를 압축시켜서 전송하기 위해서는 uncompress, compress등의 압축명령을 주로 사용한다. 이들 내용에 대해서는 자세히 다루지 않을 것이다. 직접 구현해보는 것도 매우 재미있을 것이다.
댓글 없음:
댓글 쓰기