压缩和解压技术应用很广泛,比如游戏程序中的资源管理器可以使用压缩技术将许多文件打包,便于管理,也节约了空间。本文介绍使用minizip进行解压。由于可以使用zip工具比如winzip,betterzip等进行压缩,所以本文并未涉及压缩。

 

minizip++

 

我编写了一个简单的类,与minizip和zlib一起(实际上,Mac OSX中包括了zlib库,但其他平台不一定有zlib库,所以我将其包括在源码中),构成了minizip++。此类仅包含一个类zip::CReader,此类只包括一个函数openFile用于从zip文件中读取一个文件。

 

范例概述

 

本示例程序很简单,它从data.zip文件中提取data/hello.txt显示于屏幕上,有兴趣的话,你可以扩展此程序,从zip中提取图像然后显示出来。

 

废话少说,下面介绍程序:

  • 1. 先建立一个View based Xcode项目ziptest,再创建一个目录data,在此目录下建立一个文本文件hello.txt,编辑此文本文件,加入你想在屏幕上显示的内容,比如,我在hello.txt中加入“Hello World!”。压缩data目录,然后将压缩文件data.zip加入Xcode的resource。(注意:此时加入的zip文件将出现在Targets下的“Link Binary With Libraries”下,编译时会出现一个警告,zip文件将不会被加入到.app中。所以你应该将data.zip移动到”Copy Bundle Resources”下)
  • 2. ziptestViewController.h部分如下:
    1
    2
    3
    4
    5
    @interface ziptestViewController : UIViewController {
        UILabel* _mytext;
    }

    @property (nonatomic,retain) IBOutlet UILabel* _mytext;
  • 3. 将ziptestViewController.m重命名为ziptestViewController.mm,部分代码如下:
  • 4. 双击ziptestViewController.xib打开Interface Builder。添加一个Label。Control+点击File Owner拖动到新建的Label,选取_mytext。
  • 5.然后加入header和library搜索路径。比如,我的Header Search Paths为:../../external/minizip++。然后按iphone项目使用静态库的最佳方法一文中介绍的方法加入ziptest项目。
  • 6.在viewDidLoad下进入下列代码:
  • 1
    2
    3
    4
    5
        std::stringstream in;
        zip::CReader reader;
        NSString* zippath=[[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:@"data.zip"];
        reader.openFile([ziptestViewController getString:zippath],"data/hello.txt",in);
        _mytext.text =  [NSString stringWithCString:in.str().c_str()];
  • 6. 按Build and Go运行程序。
  •  

    minizip++中CReader类中用于解压的代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    namespace zip
    {
       
        void CReader::openFile(const std::string& zip,const std::string& file,std::iostream& in)
        {
            unzFile uf=NULL;
                   
            // open zip file
    #ifdef USEWIN32IOAPI
                   zlib_filefunc_def ffunc;
                   fill_win32_filefunc(&ffunc);
                   uf = unzOpen2(zip.c_str(),&ffunc);
    #else
            uf = unzOpen(zip.c_str());
    #endif
                    if (uf==NULL)
            {
                printf("No zip file found!\n");
                return;
            }
           
            // find the file inside zip    
            if ( unzLocateFile(uf,file.c_str(),0) != UNZ_OK )
            {
                printf("%s not found in zip\n",file.c_str());
                return;
            }
           
            // file founded,extract it into the stream
            // open it
            if ( unzOpenCurrentFile(uf) != UNZ_OK )
            {
                // TODO: error handling
                printf("unzOpenCurrentFile error\n");
                return;
            }
               
            // get the file info
            char filename_inzip[256];
            int err=UNZ_OK;
               
            unz_file_info file_info;
            err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
               
            if (err!=UNZ_OK)
            {
                // TODO: error handling
                printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
                return;
            }
               
            // read the file into stream
            char* buf = (char*)malloc(file_info.uncompressed_size);
            if ( unzReadCurrentFile(uf,buf,file_info.uncompressed_size) < 0 )
            {
                // TODO: error handling
                printf("error in unzReadCurrentFile!\n");
                free(buf);
                return;
            }
               
            // write to istream
            in.rdbuf()->sputn(buf,file_info.uncompressed_size);
            free(buf);
               
            unzCloseCurrentFile(uf);
           
            unzClose(uf);
        }
    }

     

    源码下载

     

    ziptest

     

    注意:编译时,你需要修改头文件路径或者按照我的路径解压源代码。我的路径如下:

     


    root
    |—— external
    |———– minizip++

    |—— test
    |———– ziptest

     

    minizip++