C/C++에서 압축 파일을 다루는 방법이 궁금합니다.

HDNua의 이미지

안녕하세요. 초보 개발자 rbfwmqwntm입니다.
C/C++에서 zip, rar과 같은 압축 파일을 다루는 방법이 궁금합니다.
C zip, C++ zip 등과 같이 구글에서 검색해보았는데도 잘 나오지를 않네요.

사실 저는 Objective-C를 주력으로 iPhone 게임을 개발하고 있습니다.
얼마 전에 App Store에 중학생 분들이 좋아하실 법한 미궁 게임을 만들어 올렸지요.
iTunes App Store Download Link: https://itunes.apple.com/kr/app/molae-migung/id575833806?mt=8
관련 포스트: http://blog.naver.com/rbfwmqwntm/30151111903
(깨알같은 광고.. ㅎㅎ.)

이 게임을 개발할 때, 나름 스크립트 언어를 작성하고 이걸 이용해서 스테이지를 만들었습니다.
이 방식이 HTML의 그것과 비슷해서 다른 분들도 배우기 쉬울 것 같고, 나중에 개발 도구도 앱스토어에 올릴 예정입니다.
이러다보니 문득 생각이 드는 게, 다른 사람들이 제 스크립트 언어를 이용해 게임을 완성하면
이걸 네이버 카페에서 다운로드받아서 바로 다른 사람이 만든 게임을 실행해보는 방식이면 좋겠다는 생각이 들었습니다.

정리하면 이렇습니다.
1. 게임을 실행하고, [더 많은 미궁] 같은 버튼을 누릅니다.
2. 네이버 카페로 앱 내에서 이동하고, 다른 사람이 만든 미궁 게임을 다운로드받습니다.
3. 다운로드받은 게임을 실행합니다.

대충 이런 꼴인데, 이걸 하려니 이런 생각이 들더라구요.
1. 사용자가 스크립트 언어를 기반으로 소스 코드를 만듭니다. (스테이지당 소스 코드 하나를 갖습니다.)
2. 만든 소스 코드들을 압축하여 하나의 파일로 만들어 카페에 올립니다. (<- 이 과정)
3. 이 파일을 다운로드받으면, 프로그램 내부에서 압축을 풀고 소스 코드를 순서에 맞춰 실행합니다.

이렇게 되어야 말이 맞을 것 같아서 zip에 대한 정보를 찾아봤는데, 이게 참 어렵네요.
다른 건 Foundation이든 뭐든, 기본으로 프레임워크에서 제공하는 기능이라 저작권 문제 같은 것 없이 쓸 수 있는데
zip은... 이게 공개되어서 마음대로 쓸 수 있는 기술인지, 사용하려면 돈을 내야 하는 기술인지?
그것보다 사실 어떻게 압축을 풀어서 프로그램이 해석할 수 있는 데이터로 만드는가 하는 게 더 급한 문제긴 합니다만.
일단 제목에 Objective-C가 아니라 C/C++을 주제로 올린 건, 많이 사용되는 C와 C++에서 zip을 다루는 방법을 알면
자연히 그런 방식으로 Objective-C에 대한 방법도 얻을 것 같아서였습니다.

긴 글 읽어주셔서 감사합니다. 고수 분들의 조언 바랄게요!

Prentice의 이미지

우선 iOS SDK에서 zlib을 지원하는지 알아보시고, 꼭 zip이 필요하시면 info-zip을 알아보세요.

HDNua의 이미지

사실 어떤 형식이든 여러 개의 소스 파일을 묶을 수만 있다면 상관 없었습니다. rar이든, zip이든...
(이것 때문에, 그냥 압축을 포기하고 소스를 통째로 합치는 프로그램을 만들까도 생각해봤는데, 역시 용량 제한이 문제네요.)

좋은 정보 감사합니다. 그런데 위 질문에서도 궁금한 점을 여쭤봤는데, zip과 같은 건 완전히 공개된 기술인가요?
그러니까.. 사용자가 마음대로 작성할 수 없고, 이를 응용한 프로그램을 만들어 배포할 때 일정 비용을 지불해야 한다던지..?

저는 이렇게 생각했습니다.

lithium81의 이미지

http://en.wikipedia.org/wiki/Zlib_License


http://www.zlib.net/zlib_license.html


위 링크에 보시면, 1. ... 2. ... 3. ... 이라 명시한 부분만 준수한다면 상업적인 용도로도, 수정, 배포도 가능하다고 하고 있네요.


- 어제보다 나은 오늘, 오늘보다 나은 내일.

HDNua의 이미지

영어가 아직 부족해 나름의 실력으로 해석해보았습니다.

-----

/* zlib.h -- interface of the 'zlib' general purpose compression library
version 1.2.7, May 2nd, 2012

Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
이 소프트웨어는 어떤 표현이나 암시된 보장 없이 'as-is'를 제공합니다. (1)
이 소프트웨어를 사용함으로써 발생하는 어떤 문제에도 제작자들이 책임을 지지 않습니다.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
상용 애플리케이션을 포함해, 이 소프트웨어를 어떤 목적으로든 사용, 변경 또는 재분배하는
것은 누구에게나 자유롭게 허가되어있습니다만, 다음의 제한이 따릅니다.

(misrepresented? 네이버 검색에는 '허구의'라고 나오는데 의미가 좀 다르지 않나 궁금합니다.)
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
1. 이 소프트웨어의 원본은 당신 것이 아닙니다. 당신 스스로 이 소프트웨어의 제작자라고
사칭하지 마십시오. 이 소프트웨어를 상업적인 용도로 사용한다면 제품 문서에 이를
알려주시면 감사합니다만 필수는 아닙니다.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
2. 소스 버전을 변경하였다면 변경된 바를 간단하게 적어주시되, 이 파일이 원래의
소프트웨어라고 하지는 마십시오. (2)
3. This notice may not be removed or altered from any source distribution.
3. 이 알림은 어떤 소스 버전에서도 없어지거나 바뀌지 않을 것입니다.

Jean-loup Gailly Mark Adler
jloup@gzip.org madler@alumni.caltech.edu
*/

-----

1. 전반적으로 맞게 해석된 것 같나요..?
2. 각 문장에 표기하였습니다.
(1) as-is를 제공한다고 하는데... 이게 무슨 뜻인지?
(2) plainly marked as such가.. 해석이 헷갈립니다.
(갑자기 영어 문법 시간이 된 것 같네요ㅋㅋㅋㅋ)

저는 이렇게 생각했습니다.

jick의 이미지

This software is provided "as is" without any express or implied warranty: 이 소프트웨어는 있는 그대로 (소프트웨어만의 상태로) 제공되며, (이 소프트웨어가 원하는 동작을 할 거라는) 어떤 명시적(express) 혹은 암시적인 보장도 없습니다. (다시 말해서 부가 서비스, 품질보증, 오동작시 손해보상 등등은 기대하지 말라는 뜻입니다.)

The origin of this software must not be misrepresented: 이 소프트웨어의 원천에 대해 잘못된 사실을 얘기하지 마십시오. (그러니까 "이거 제가 첨부터 다 짠 거예요!" 같은 소리 하지 말라는 거죠.)

Altered source versions must be plainly marked as such: 변경된 소스 버전은 변경되었다고 *알아보기 쉽게* 표시가 되어 있어야 합니다. 즉, 소스를 변경했다면 "xxx가 변경했음"이라고 표시해서 원본 소프트웨어와 혼동이 생기지 않도록 해야 합니다.

3. This notice may not be... : 어떤 소스 배포판에서도 이 알림을 없애거나 바꿔서는 *안됩니다*.

HDNua의 이미지

많은 도움이 되었습니다! ㅎㅎ

저는 이렇게 생각했습니다.

HDNua의 이미지

zlib 라이브러리를 통해 파일을 압축하는 방법까지는 적당히 코드로 짜봤었습니다.
그런데 아래 사이트에서 정보를 찾아보니, zlib는 Unicode는 지원하지 않는다고 나와있어버리네요.
(한글이 들어가지 않을 수가 없는 프로그램입니다ㅠㅠ)
http://anster.egloos.com/2165172

그래서 다시 한 번 KLDP 분들께 여쭤봅니다.
C/C++에서 압축 파일을 다룰 수 있는 라이브러리 중 유니코드를 지원하는 공개 라이브러리가 있을까요?

혹시 몰라 제가 연습용으로 작성했던 소스 코드를 같이 올려봅니다. 이 코드에서 수정해야 할 부분도 알려주시면 감사하겠습니다.
HDData는 데이터, HDLNode는 LinkedListNode의 약자로 HDData data; HDLNode *next;를 구조체의 멤버로 갖고 있습니다.
HDList는 HDLNode를 기반으로 작성한 연결 리스트입니다.

#include <zlib.h>
 
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
 
#include "HDLib.h"
#include "HDList.h"
 
#define NAME_MAX    256
#define BUF_MAX     1024
 
#define ClearReadBuffer() while(getchar()!='\n')
 
int ArchiveData(gzFile *zfp, const HDList *plist);
 
int main(void)
{
    char ch;
    HDList flist;
    char tmpName[NAME_MAX];
 
    gzFile *zfp;
    int fd;
 
    // Initialize list
    HDListInit(&flist);
 
    // Get File Data From Standard Input Stream
    do
    {
        printf("0. Make file\n");
        printf("1. Add files to list\n");
        printf("2. Show added file's list\n");
        printf("3. Archive data\n");
        printf("4. Extract File\n");
        printf(">> ");
        scanf("%c", &ch);
        ClearReadBuffer();
 
        switch (ch)
        {
            case '0':
                printf("Enter the name you want: ");
                scanf("%s", tmpName);
                if (access(tmpName, F_OK)==0)
                {
                    printf("Error: Already exists\n");
                    break;
                }
                if (!fopen(tmpName, "wb"))
                {
                    printf("Error: Cannot create file named %s\n", tmpName);
                    break;
                }
                break;
 
            // Add files to list
            case '1':
                printf("Enter the name of target: ");
                fgets(tmpName, NAME_MAX, stdin);
                tmpName[strlen(tmpName)-1]=0;
//                printf("File's name: %s\n", tmpName);
 
                // Check the original file exists
                if (access(tmpName, F_OK)!=0)
                {
                    printf("Error: File %s does not exist\n", tmpName);
                    break;
                }
                fd = open(tmpName, O_RDONLY);
                if (fd<0)
                {
                    printf("Error: Cannot open file %s\n", tmpName);
                    break;
                }
                HDListAddValue(&flist, fd);
                break;
 
            // Show added file's list
            case '2':
                printf("Number of file: %d\n", flist.len);
                HDListShow(&flist);
                break;
 
            // Archive data
            case '3':
                strcpy(tmpName, "Test.gz");
                zfp = gzopen(tmpName, "wb");
                if (!zfp)
                {
                    printf("Error: Cannot create file %s\n", tmpName);
                    break;
                }
                if (ArchiveData(zfp, &flist))
                {
                    printf("Error: Cannot complete archiving data\n");
                    break;
                }
                gzclose(zfp);
                break;
 
            // Extract File
            case '4':
                break;
 
            // Input error: try again
            default:
                printf("Try again\n");
                continue;
        }
        if (NAME_MAX<=strlen(tmpName))
            ClearReadBuffer();
 
        printf("Try again(y/n)? ");
        scanf("%c", &ch);
        ClearReadBuffer();
 
    } while (toupper(ch)!='N');
 
    HDListDealloc(&flist);
    return 0;
}
 
int ArchiveData(gzFile *zfp, const HDList *plist)
{
    int i;
    int n, lerrno;
    char buf[BUF_MAX];
    HDLNode *pnode = plist->phead;
 
    if (HDListIsEmpty(plist))
        return HDLIST_IS_EMPTY;
 
    for (i=0; i<plist->len; ++i)
    {
        while ((n=(int)read(pnode->data.value, buf, BUF_MAX))>0)
            if (gzwrite(zfp, buf, n)<0)
            {
                printf("%s\n", gzerror(zfp, &lerrno));
                return -1;
            }
        pnode = pnode->next;
    }
 
    return 0;
}

저는 이렇게 생각했습니다.

Prentice의 이미지

Unicode 지원은 내용 얘기가 아니라 파일/경로 처리 관련 문제입니다.

Unicode 경로 지원은 리눅스에선 잘 됩니다. 맥/iOS에서도 잘 될 듯요.

문제는 D:\똠방각하\펲시맨\이와이슌지.txt를 압축할 때 경로명 때문에 골치가 아플 수 있다는 점 뿐입니다. 참고로 3월 쯤에 zlib 개발자가 다음 버전에선 관련 함수를 추가해서 수정할 거라고 했나 보네요.

HDNua의 이미지

알고 보니 파일 확장자를 잘못 만들어서 제대로 읽지 못했던 것 뿐이었네요. ㅎㅎ

저는 이렇게 생각했습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.