是否可以在不提取Objective-C文件的情况下读取压缩文件?

时间:2012-02-15 08:07:10

标签: iphone objective-c ipad zip gzip

我正在构建一个应用程序,它需要读取zipfile中的文件而不提取文件。有没有这种功能的图书馆,或者你可以给我一些如何解决它的想法?

1 个答案:

答案 0 :(得分:2)

您可以一次解压缩一个缓冲区数据,并读取它,假设该文件是文本并且以可以递增地解析它的方式构造(例如,使用a处理的XML数据) SAX解析器。)

这是我编写的一个例程,它从zip流中提取数据并一次打印出一行。您可以修改它以打印或解析N个字符。或者您可以将行添加到行缓冲区,并一次处理/解析一大块行。

这使用zlib,如果此代码对您有用,请随时使用:

#
# compile with -lz option in order to link in the zlib library
#

#include <zlib.h>

#define Z_CHUNK 2097152

int unzipFile(const char *fName) 
{
    z_stream zStream;
    char *zRemainderBuf = malloc(1);
    unsigned char zInBuf[Z_CHUNK];
    unsigned char zOutBuf[Z_CHUNK];
    char zLineBuf[Z_CHUNK];
    unsigned int zHave, zBufIdx, zBufOffset, zOutBufIdx;
    int zError;
    FILE *inFp = fopen(fName, "rbR");

    if (!inFp) { fprintf(stderr, "could not open file: %s\n", fName); return EXIT_FAILURE; }

    zStream.zalloc = Z_NULL;
    zStream.zfree = Z_NULL;
    zStream.opaque = Z_NULL;
    zStream.avail_in = 0;
    zStream.next_in = Z_NULL;  

    zError = inflateInit2(&zStream, (15+32)); /* cf. http://www.zlib.net/manual.html */
    if (zError != Z_OK) { fprintf(stderr, "could not initialize z-stream\n"); return EXIT_FAILURE; }

    *zRemainderBuf = '\0';
    do {
        zStream.avail_in = fread(zInBuf, 1, Z_CHUNK, inFp);
        if (zStream.avail_in == 0)
            break;
        zStream.next_in = zInBuf;
        do {
            zStream.avail_out = Z_CHUNK;
            zStream.next_out = zOutBuf;
            zError = inflate(&zStream, Z_NO_FLUSH);
            switch (zError) {
                case Z_NEED_DICT:  { fprintf(stderr, "Z-stream needs dictionary!\n"); return EXIT_FAILURE; }
                case Z_DATA_ERROR: { fprintf(stderr, "Z-stream suffered data error!\n"); return EXIT_FAILURE; }
                case Z_MEM_ERROR:  { fprintf(stderr, "Z-stream suffered memory error!\n"); return EXIT_FAILURE; }
            }
            zHave = Z_CHUNK - zStream.avail_out;
            zOutBuf[zHave] = '\0';

            /* copy remainder buffer onto line buffer, if not NULL */
            if (zRemainderBuf) {
                strncpy(zLineBuf, zRemainderBuf, strlen(zRemainderBuf));
                zBufOffset = strlen(zRemainderBuf);
            }
            else
                zBufOffset = 0;

            /* read through zOutBuf for newlines */
            for (zBufIdx = zBufOffset, zOutBufIdx = 0; zOutBufIdx < zHave; zBufIdx++, zOutBufIdx++) {
                zLineBuf[zBufIdx] = zOutBuf[zOutBufIdx];
                if (zLineBuf[zBufIdx] == '\n') {
                    zLineBuf[zBufIdx] = '\0'; 
                    zBufIdx = -1;
                    fprintf(stdout, "%s\n", zLineBuf);
                }
            }

            /* copy some of line buffer onto the remainder buffer, if there are remnants from the z-stream */
            if (strlen(zLineBuf) > 0) {
                if (strlen(zLineBuf) > strlen(zRemainderBuf)) {
                    /* to minimize the chance of doing another (expensive) malloc, we double the length of zRemainderBuf */
                    free(zRemainderBuf);
                    zRemainderBuf = malloc(strlen(zLineBuf) * 2);
                }
                strncpy(zRemainderBuf, zLineBuf, zBufIdx);
                zRemainderBuf[zBufIdx] = '\0';
            }
        } while (zStream.avail_out == 0);
    } while (zError != Z_STREAM_END);

    /* close gzip stream */
    zError = inflateEnd(&zStream);
    if (zError != Z_OK) { 
        fprintf(stderr, "could not close z-stream!\n");
        return EXIT_FAILURE;
    }
    if (zRemainderBuf)
        free(zRemainderBuf);

    fclose(inFp);

    return EXIT_SUCCESS;
}