[zip]android下实现直接读取zip中的文件

来源:互联网 发布:谷歌网站seo教程 编辑:程序博客网 时间:2024/05/16 08:27

     不用解压,直接读取zip中指定的文件,例如文件/sdcard/a.zip中有文件z.txt,读取步骤如下:

[cpp] view plaincopy
  1. int zfd = zip_open("/sdcard/a.zip/z.txt");  
  2. if (ZIP_IS_VALID(zfd)) {  
  3.     zip_seek(zfd, 5, SEEK_SET);  
  4.     zip_read(zfd, buf, 10);  
  5.     zip_close(zfd);  
  6. }  

1.依赖于android framework中的ZipFileRO.h,要求在android系统源码环境中编译;

2.目前只支持以“存储“格式压缩的zip文件;

3.主要接口:

[cpp] view plaincopy
  1. int zip_open(const char* path);  
  2. int zip_close(int handle);  
  3. int zip_read(int handle, void *buf, int count);  
  4. int zip_seek(int fd, int offset, int whence);  
  5. int zip_stat(const char *file_name, struct stat *buf);  

zip_wrapper.h

[cpp] view plaincopy
  1. /* 
  2.  * read a file in zip as normal file. 
  3.  * only support kCompressStored method 
  4.  *  
  5.  * dependent on android ZipFileRO.h 
  6.  * build in AOSP 
  7.  * 
  8.  * zip_open  
  9.  * zip_close 
  10.  * zip_read 
  11.  * zip_seek 
  12.  * zip_stat 
  13.  */  
  14.   
  15. #ifndef _ZIP_WRAPPER_H_  
  16. #define _ZIP_WRAPPER_H_  
  17.   
  18. #include <unistd.h>  
  19. #include <sys/types.h>  
  20. #include <sys/stat.h>  
  21. #include <errno.h>  
  22. #include <fcntl.h>  
  23.   
  24. #include <android/log.h>  
  25.   
  26.   
  27. #ifdef __cplusplus  
  28. extern "C" {  
  29. #endif  
  30.   
  31. #define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)  
  32. #define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)  
  33. #define LOGW(...)  __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)  
  34. #define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)  
  35. #define LOGF(...)  __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__)  
  36.   
  37. #define ZIP_IS_VALID(f) ((f) != 0)  
  38.   
  39. int zip_open(const char* path);  
  40. int zip_close(int handle);  
  41. int zip_read(int handle, void *buf, int count);  
  42. int zip_seek(int fd, int offset, int whence);  
  43. int zip_stat(const char *file_name, struct stat *buf);  
  44.   
  45. #ifdef __cplusplus  
  46. }  
  47. #endif  
  48.   
  49. #endif //#ifndef _ZIP_WRAPPER_H_  

zip_wrapper.cpp

[cpp] view plaincopy
  1. #define LOG_TAG "zip_wrapper"  
  2.   
  3. #include <utils/ZipFileRO.h>  
  4. #include "zip_wrapper.h"  
  5.   
  6. using namespace android;  
  7.   
  8. extern "C" {  
  9.   
  10. #define ZIP_FLAG ".zip/"  
  11. #define ZIP_FLAG_LEN strlen(ZIP_FLAG)  
  12.   
  13. static int is_file(const char* path)  
  14. {  
  15.     int ok = 0;  
  16.     struct stat buf;  
  17.       
  18.     int ret = stat(path, &buf);  
  19.     if (ret == 0) {  
  20.         if (S_ISREG(buf.st_mode)) {  
  21.             ok = 1;//is file  
  22.         } else {  
  23.             //LOGI("%s is not a file !", path);  
  24.         }  
  25.     } else {  
  26.         LOGI("%s is not exist ! ret = %d", path, ret);  
  27.     }  
  28.       
  29.     return ok;  
  30. }  
  31.   
  32. static int is_dir(const char* path)  
  33. {  
  34.     int ok = 0;  
  35.     struct stat buf;  
  36.       
  37.     int ret = stat(path, &buf);  
  38.     if (ret == 0) {  
  39.         if (S_ISDIR(buf.st_mode)) {  
  40.             ok = 1;//is dir  
  41.         } else {  
  42.             //LOGI("%s is not a dir !", path);  
  43.         }  
  44.     } else {  
  45.         LOGI("%s is not exist !", path);  
  46.     }  
  47.       
  48.     return ok;  
  49. }  
  50.   
  51. static int get_zip_path(const char* path, char* zippath)  
  52. {  
  53.     int ok = 0;  
  54.     const char* p = NULL;  
  55.   
  56.     p = strstr(path, ZIP_FLAG);   
  57.     if (p && (p + ZIP_FLAG_LEN != path + strlen(path))) {  
  58.         if (zippath) {  
  59.             strncpy(zippath, path, p + ZIP_FLAG_LEN - 1 - path);  
  60.             LOGI("zip path: %s", zippath);  
  61.         } // else, just judge the path is ok  
  62.         ok = 1;  
  63.     }  
  64.   
  65.     return ok;  
  66. }  
  67.   
  68. static int get_path_in_zip(const char* path, char* pathinzip)  
  69. {  
  70.     int ok = 0;  
  71.     const char* p = NULL;  
  72.       
  73.     p = strstr(path, ZIP_FLAG);   
  74.     if (p && (p + ZIP_FLAG_LEN != path + strlen(path))) {  
  75.         if (pathinzip) {  
  76.             strcpy(pathinzip, p + ZIP_FLAG_LEN);  
  77.             //LOGI("path in zip: %s", pathinzip);  
  78.         } // else, just judge the path is ok  
  79.         ok = 1;  
  80.     }  
  81.   
  82.     return ok;  
  83. }  
  84.   
  85. // whether or not the file is in zip   
  86. // /xxx/a.zip/b.txt  return true if a.zip is a file, else false  
  87. // /xxx/a.zip/       return false  
  88. // /xxx/a.zip        return false  
  89. // /xxx/a.txt        return false  
  90. //  
  91. int is_in_zip(const char* path)  
  92. {  
  93.     int iszip = 0;  
  94.     struct stat buf;  
  95.     char zippath[PATH_MAX] = {0};  
  96.   
  97.     if (path == NULL) {  
  98.         LOGE("is_in_zip() path is null !");  
  99.         return iszip;  
  100.     }  
  101.       
  102.     int ret = stat(path, &buf);  
  103.     //LOGI("PATH_MAX = %d", PATH_MAX);  
  104.     LOGI("path: %s", path);  
  105.     if (ret < 0) { // failed, maybe /xxx/a.zip/b.txt or no exist  
  106.         if (get_zip_path(path, zippath)) {  
  107.             if (is_file(zippath)) {  
  108.                 LOGI("%s is in zip: %s", path, zippath);  
  109.                 iszip = 1; // OK  
  110.             } else {  
  111.                 LOGI("%s is not a zip", zippath);  
  112.             }  
  113.         } else {  
  114.             LOGI("%s is not exist!", path);  
  115.         }  
  116.     } else {  
  117.         if (S_ISDIR(buf.st_mode)) {  
  118.             LOGI("%s is a dir", path);  
  119.         } else if (S_ISREG(buf.st_mode)) {  
  120.             LOGI("%s is a file", path);  
  121.         } else {  
  122.             LOGI("%s not a file or dir", path);  
  123.         }  
  124.     }  
  125.     return iszip;  
  126. }  
  127.   
  128. /******************************************************************/  
  129.   
  130. typedef struct _zip_priv {  
  131.     ZipFileRO * zip;  
  132.     ZipEntryRO entry;  
  133.     FileMap * map;  
  134.     off_t offset;  
  135. }zip_priv;  
  136.   
  137. static zip_priv * _zip_priv_open(const char * path)  
  138. {  
  139.     char zippath[PATH_MAX] = {0};  
  140.     char filepath[256] = {0};  
  141.     get_zip_path(path, zippath);  
  142.     get_path_in_zip(path, filepath);  
  143.   
  144.     int fd = 0;  
  145.     zip_priv * zp = NULL;  
  146.       
  147.     ZipFileRO * zip = new ZipFileRO();  
  148.     ZipEntryRO entry = NULL;  
  149.     FileMap* map = NULL;  
  150.       
  151.     do  
  152.     {  
  153.         if (zip->open(zippath) != NO_ERROR) {  
  154.             LOGE("zip->open(%s) failed!", zippath);  
  155.             break;  
  156.         }  
  157.   
  158.         entry = zip->findEntryByName(filepath);  
  159.         if (entry == 0) {  
  160.             LOGE("zip->findEntryByName(%s) failed!", filepath);  
  161.             break;  
  162.         }  
  163.           
  164.         int method = 0;  
  165.         if (!zip->getEntryInfo(entry, &method, 0, 0, 0, 0, 0)) {  
  166.             LOGE("zip->getEntryInfo() failed!");  
  167.             break;  
  168.         }  
  169.         // only support stored method  
  170.         if (method != ZipFileRO::kCompressStored) {  
  171.             LOGE("error: not support, method = %d !\n"  
  172.             "only support kCompressStored", method);  
  173.             break;  
  174.         }  
  175.           
  176.         map = zip->createEntryFileMap(entry);  
  177.         if (map == 0) {  
  178.             LOGE("zip->createEntryFileMap(%p) failed!", entry);  
  179.             break;  
  180.         }  
  181.           
  182.         zp = (zip_priv *)malloc(sizeof(zip_priv));  
  183.         if (zp == NULL) {  
  184.             LOGE("malloc(sizeof(zip_priv)) failed !");  
  185.             break;  
  186.         }  
  187.           
  188.         memset(zp, 0, sizeof(zip_priv));          
  189.         zp->zip    = zip;  
  190.         zp->entry  = entry;  
  191.         zp->map    = map;  
  192.         zp->offset = 0;  
  193.           
  194.         fd = (int)zp; //ok  
  195.     }while(0);  
  196.       
  197.     if (fd == 0) {  
  198.         if (map) map->release();  
  199.         if (zip) delete zip;  
  200.         if (zp) free(zp);  
  201.         LOGI("_zip_open(%s) failed !", path);  
  202.     } else {  
  203.         LOGI("_zip_open(%s) ok !", path);  
  204.     }  
  205.       
  206.     return zp;  
  207. }  
  208.   
  209. static int _zip_open(const char * path)  
  210. {  
  211.     return (int)_zip_priv_open(path);  
  212. }  
  213.   
  214. static int _zip_close(int handle)  
  215. {  
  216.     int ret = -1;  
  217.     zip_priv * zp = (zip_priv*)handle;  
  218.     if (zp) {  
  219.         zp->map->release();  
  220.         delete zp->zip;  
  221.         free(zp);  
  222.         ret = 0;  
  223.     }     
  224.     return ret;  
  225. }  
  226.   
  227. static ssize_t _zip_read(int handle, void *buf, size_t count)  
  228. {  
  229.     int ret = -1;  
  230.     zip_priv * zp = (zip_priv*)handle;  
  231.     if (zp) {  
  232.         size_t max = zp->map->getDataLength() - zp->offset;  
  233.         max = max < count ? max : count;  
  234.         if (max > 0) {  
  235.             memcpy(buf, ((char *)zp->map->getDataPtr()) + zp->offset, max);  
  236.             zp->offset += max;  
  237.         }  
  238.         ret = max;  
  239.     }  
  240.     return ret;  
  241. }  
  242.   
  243. static off_t _zip_seek(int handle, off_t offset, int whence)  
  244. {  
  245.     int ret = -1;  
  246.     zip_priv * zp = (zip_priv*)handle;  
  247.     off_t _offset, datalen;  
  248.       
  249.     if (zp) {  
  250.         _offset = zp->offset;  
  251.         datalen = zp->map->getDataLength();  
  252.         switch(whence) {  
  253.             case SEEK_SET:  
  254.                 _offset = offset;  
  255.                 break;  
  256.             case SEEK_CUR:  
  257.                 _offset += offset;  
  258.                 break;  
  259.             case SEEK_END:  
  260.                 _offset = datalen + offset;  
  261.                 break;  
  262.             default:  
  263.                 LOGE("_zip_seek not support whence: %d", whence);  
  264.                 break;  
  265.         }  
  266.         if (_offset != zp->offset) {  
  267.             _offset = _offset >= 0 ? _offset : 0;  
  268.             zp->offset = _offset <= datalen ? _offset : datalen;    
  269.         }  
  270.         ret = zp->offset;  
  271.     }  
  272.   
  273.     return ret;  
  274. }  
  275.   
  276. /* 
  277. buf->st_size 
  278. buf->st_mode & S_IFREG 
  279. buf->st_mode & S_IFDIR 
  280. buf->st_mtime 
  281. */  
  282. static int _zip_stat(const char *file_name, struct stat *buf)  
  283. {  
  284.     int ret = -1;  
  285.     zip_priv * zp = _zip_priv_open(file_name);  
  286.     do   
  287.     {  
  288.         if (zp == NULL) {  
  289.             break;  
  290.         }  
  291.           
  292.         memset(buf, 0, sizeof(struct stat));  
  293.           
  294.         size_t uncompLen = 0;  
  295.         if (!zp->zip->getEntryInfo(zp->entry, 0, &uncompLen, 0, 0, 0, 0)) {  
  296.             LOGE("zp->zip->getEntryInfo() failed !");  
  297.             break;  
  298.         }  
  299.         LOGI("uncompLen = %d", uncompLen);  
  300.         buf->st_size = uncompLen;  
  301.           
  302.         char name[256] = {0};  
  303.         if (zp->zip->getEntryFileName(zp->entry, name, sizeof(name)) == -1) {  
  304.             LOGE("zp->zip->getEntryFileName() failed !");  
  305.             break;  
  306.         }  
  307.         if (name[strlen(name) - 1] == '/') {  
  308.             buf->st_mode = S_IFDIR;  
  309.             LOGI("%s is a dir", name);  
  310.         } else {  
  311.             buf->st_mode = S_IFREG;  
  312.             LOGI("%s is a file", name);  
  313.         }  
  314.           
  315.         buf->st_mtime = 0;  
  316.         ret = 0;  
  317.     }while(0);  
  318.       
  319.     if (zp) {  
  320.         _zip_close((int)zp);  
  321.     }  
  322.       
  323.     return ret;  
  324. }  
  325.   
  326. /******************************************************************/  
  327. typedef struct _fs_operator {  
  328.     int     (*close)(int handle);  
  329.     ssize_t (*read) (int handle, void *buf, size_t count);  
  330.     off_t   (*seek) (int handle, off_t offset, int whence);  
  331. } fs_operator;  
  332.   
  333. typedef struct _zip_info {  
  334.     const fs_operator * opt;  
  335.     int fd;  
  336. } zip_info;  
  337.   
  338. static const fs_operator s_operator[] =   
  339. {  
  340.     {  
  341.         close,   
  342.         read,   
  343.         lseek,   
  344.     },  
  345.     {  
  346.         _zip_close,   
  347.         _zip_read,   
  348.         _zip_seek,   
  349.     },  
  350. };  
  351.   
  352. /******************************************************************/      
  353. // api  
  354.   
  355. int zip_open(const char* path)  
  356. {  
  357.     int zfd = 0;  
  358.     zip_info * pz = NULL;  
  359.       
  360.     if (path == NULL) {  
  361.         LOGE("zip_open: path is null");  
  362.         return -1;  
  363.     }  
  364.   
  365.     do   
  366.     {  
  367.         pz = (zip_info *) malloc(sizeof(zip_info));  
  368.         if (pz == NULL) {  
  369.             LOGE("malloc(sizeof(zip_info)) failed !");  
  370.             break;  
  371.         }  
  372.         memset(pz, 0, sizeof(zip_info));  
  373.           
  374.         int fd = 0;  
  375.         if (is_in_zip(path)) {  
  376.             fd = _zip_open(path);  
  377.             if (!fd) {  
  378.                 break;  
  379.             }  
  380.             pz->opt = &s_operator[1];  
  381.         } else {  
  382.             fd = open(path, O_RDONLY);  
  383.             if (fd < 0) {  
  384.                 LOGE("open(%s) failed!", path);  
  385.                 break;  
  386.             }  
  387.             pz->opt = &s_operator[0];  
  388.         }  
  389.         pz->fd = fd;  
  390.         zfd = (int)pz;  
  391.     }while(0);  
  392.   
  393.     if (!ZIP_IS_VALID(zfd)) {  
  394.         if (pz) free(pz);  
  395.     }  
  396.       
  397.     return zfd;  
  398. }  
  399.   
  400. int zip_close(int handle)  
  401. {  
  402.     int ret = -1;  
  403.     zip_info * pz = (zip_info *)handle;  
  404.     if (pz) {  
  405.         ret = pz->opt->close(pz->fd);  
[cpp] view plaincopy
  1. <span style="white-space:pre">      </span>free(pz);  
  2.     }  
  3.     return ret;  
  4. }  
  5.   
  6. int zip_read(int handle, void *buf, int count)  
  7. {  
  8.     int ret = -1;  
  9.     zip_info * pz = (zip_info *)handle;  
  10.     if (pz) {  
  11.         ret = pz->opt->read(pz->fd, buf, count);  
  12.     }  
  13.     return ret;  
  14. }  
  15.   
  16. int zip_seek(int handle, int offset, int whence)  
  17. {  
  18.     int ret = -1;  
  19.     zip_info * pz = (zip_info *)handle;  
  20.     if (pz) {  
  21.         ret = pz->opt->seek(pz->fd, offset, whence);  
  22.     }  
  23.     return ret;  
  24. }  
  25.   
  26. int zip_stat(const char *file_name, struct stat *buf)  
  27. {  
  28.     int ret = -1;  
  29.     if(file_name && buf) {  
  30.         if (is_in_zip(file_name)) {  
  31.             ret = _zip_stat(file_name, buf);  
  32.         } else {  
  33.             ret = stat(file_name, buf);  
  34.         }  
  35.     } else {  
  36.           
  37.     }  
  38.     return ret;  
  39. }  
  40.   
  41. }//extern "C" {  

zip_main.cpp

[cpp] view plaincopy
  1. #define LOG_TAG "zip_wrapper"  
  2.   
  3. #include <utils/String8.h>  
  4. #include <utils/ZipFileRO.h>  
  5.   
  6. #include "zip_wrapper.h"  
  7.   
  8. using namespace android;  
  9.   
  10. extern "C" {  
  11.     int is_in_zip(const char* path);  
  12. }  
  13.   
  14. // ---------------------------------------------------------------------------  
  15. int testReadEntry(int argc, char** argv)  
  16. {  
  17.     ZipFileRO mZip;  
  18.       
  19.     char path[256] = "/sdcard/zip/demo.zip";  
  20.       
  21.     if (argc >= 2) {  
  22.         strcpy(path, argv[1]);  
  23.     }  
  24.   
  25.     LOGI("path: %s\n", path);  
  26.   
  27.     mZip.open(path);   
  28.     size_t numEntries = mZip.getNumEntries();  
  29.     LOGI("numEntries: %d\n", numEntries);  
  30.     if ((int)numEntries < 0){  
  31.         return 0;  
  32.     }  
  33.   
  34.     int method = 0;  
  35.     size_t uncompLen = 0;  
  36.     size_t compLen = 0;  
  37.     off64_t offset = 0;  
  38.     long modWhen = 0;  
  39.     long crc32 = 0;  
  40.   
  41.     char name[256] = {0};  
  42.     for (size_t i=0 ; i<numEntries ; i++) {  
  43.         ZipEntryRO entry = mZip.findEntryByIndex(i);  
  44.         if (mZip.getEntryFileName(entry, name, sizeof(name)) == 0) {  
  45.             if (mZip.getEntryInfo(entry, &method, &uncompLen,   
  46.                         &compLen, &offset, &modWhen, &crc32)) {  
  47.                 LOGI("name:[%d] %s\n", i, name);  
  48.                 LOGI("method: %d\n", method);  
  49.                 LOGI("uncompLen: %d,\tcompLen: %d\n", uncompLen, compLen);  
  50.                 LOGI("offset: %lld,\tcrc32: 0x%lx\n", offset, crc32);  
  51.             }  
  52.         }  
  53.     }  
  54.   
  55.     return 0;  
  56. }  
  57.   
  58.   
  59. int testIsInZip(int argc, char** argv)  
  60. {  
  61.     if (argc < 2) {  
  62.         LOGE("parameter is error! :%s filepath", argv[0]);  
  63.         return -1;  
  64.     }  
  65.     return is_in_zip(argv[1]);  
  66. }  
  67.   
  68. int testRead(int argc, char** argv)  
  69. {  
  70.     int zfd = 0;  
  71.     char buf[100] = {0};  
  72.       
  73.     if (argc < 2) {  
  74.         LOGE("parameter is error! :%s filepath", argv[0]);  
  75.         return -1;  
  76.     }  
  77.       
  78.     zfd = zip_open(argv[1]);  
  79.     LOGI("zfd = 0x%x", zfd);  
  80.     if (ZIP_IS_VALID(zfd)) {  
  81.         zip_read(zfd, buf, 10);  
  82.         LOGI("read: %s", buf);  
  83.           
  84.         memset(buf, 0, sizeof(buf));  
  85.         zip_seek(zfd, 5, SEEK_SET);  
  86.         zip_read(zfd, buf, 10);  
  87.         LOGI("read: %s", buf);  
  88.           
  89.         zip_close(zfd);  
  90.     }  
  91.     return 0;  
  92. }  
  93.   
  94. int testStat(int argc, char** argv)  
  95. {  
  96.     struct stat buf;  
  97.       
  98.     if (argc < 2) {  
  99.         LOGE("parameter is error! :%s filepath", argv[0]);  
  100.         return -1;  
  101.     }  
  102.       
  103.     zip_stat(argv[1], &buf);  
  104.   
  105.     return 0;  
  106. }  
  107.   
  108. int main(int argc, char** argv)  
  109. {  
  110.     //testReadEntry(argc, argv);  
  111.     //testIsInZip(argc, argv);  
  112.     //testRead(argc, argv);  
  113.     testStat(argc, argv);  
  114.     return 0;  
  115. }  

Android.mk

[cpp] view plaincopy
  1. LOCAL_PATH:= $(call my-dir)  
  2.   
  3. #################################  
  4. include $(CLEAR_VARS)  
  5. LOCAL_SRC_FILES:= \  
  6.     zip_wrapper.cpp  
  7.   
  8. LOCAL_CFLAGS :=   
  9. LOCAL_SHARED_LIBRARIES := libutils   
  10.   
  11. LOCAL_C_INCLUDES := .  
  12. LOCAL_MODULE_TAGS:= optional  
  13. LOCAL_MODULE:= libreadzip  
  14. include $(BUILD_STATIC_LIBRARY)  
  15.   
  16. #################################  
  17. include $(CLEAR_VARS)  
  18. LOCAL_SRC_FILES:= \  
  19.     zip_main.cpp   
  20.       
  21. LOCAL_CFLAGS :=   
  22. LOCAL_STATIC_LIBRARIES := libreadzip  
  23. LOCAL_SHARED_LIBRARIES := libutils   
  24.   
  25. LOCAL_C_INCLUDES := .  
  26. LOCAL_MODULE_TAGS:= optional  
  27. LOCAL_MODULE:= readzip  
  28. include $(BUILD_EXECUTABLE)  
原创粉丝点击