2013-04-29 249 views

回答

3

我解決我的問題了unziping: 我添加了這個功能unzip.c

extern unzFile ZEXPORT unzOpenBuffer (const void* buffer, uLong size) 
{ 
    char path[16] = {0}; 
    zlib_filefunc64_32_def memory_file; 
    uLong base = (uLong)buffer; 

    sprintf(path, "%x+%x", base, size); 

    fill_memory_filefunc64_32(&memory_file); 
    return unzOpenInternal(path, &memory_file, 0); 
} 

及Made in ioapi_mem.c一些變化:

void fill_memory_filefunc64_32 (pzlib_filefunc_def) 
    zlib_filefunc64_32_def* pzlib_filefunc_def; 
{ 
    pzlib_filefunc_def->zopen32_file = fopen_mem_func; 
    pzlib_filefunc_def->zfile_func64.zopen64_file = fopen_mem_func; 
    pzlib_filefunc_def->zfile_func64.zread_file = fread_mem_func; 
    pzlib_filefunc_def->zfile_func64.zwrite_file = fwrite_mem_func; 
    pzlib_filefunc_def->ztell32_file = ftell_mem_func; 
    pzlib_filefunc_def->zseek32_file = fseek_mem_func; 
    pzlib_filefunc_def->zfile_func64.zseek64_file = NULL; 
    pzlib_filefunc_def->zfile_func64.zclose_file = fclose_mem_func; 
    pzlib_filefunc_def->zfile_func64.zerror_file = ferror_mem_func; 
    pzlib_filefunc_def->zfile_func64.opaque = NULL; 
} 

我希望這會幫助別人誰會有同樣的問題。

,這裏是簡單的類實現如何使用它:

void ZipArchiveImpl::OpenArchive() 
     { 
      ASSERT(!mInited, "Already opened."); 


      if ((mFileMode == FM_READ)) 
      { 
       if (mArchiveName.size() == 0) 
       { 


        u32 sz = mFile->GetFileSize(); 
        mUnzBlock.Resize(sz); 
        mFile->SetPosition(0); 
        mFile->Read(mUnzBlock.Data(), mUnzBlock.GetSizeInBytes()); 

        mUnzHandle = unzOpenBuffer(mUnzBlock.Data(), mUnzBlock.GetSizeInBytes()); 

       } 
       else 
       { 
        mUnzHandle = unzOpen(mArchiveName.c_str()); 
       } 

       if (!mUnzHandle) return; 
       FillMap(); 
      } 

      else if (mFileMode == FM_WRITE) 
      { 
       ASSERT0(mArchiveName.size()); 
       mZipHandle = zipOpen(mArchiveName.c_str(), 0); 

       if (!mZipHandle) return; 
      } 



      mInited = true; 
     } 

     IFile* ZipArchiveImpl::OpenRead(const std::string& name) 
     { 
      if (IsExist(name)) 
      { 

       ZipFileInfo info = mFileMap.find(name)->second; 

       MemoryBlock block(1); 
       block.Resize(info.uncompressedSize); 

       int res = unzGoToFilePos(mUnzHandle, &info.filePosInfo); 
       if (UNZ_OK != res) 
       { 
        return false; 
       } 

       // open the current file with optional password 
       if (mArchivePassword != "") 
       { 
        res = unzOpenCurrentFilePassword(info.zipFileHandle, mArchivePassword.c_str()); 
       } 
       else 
       { 
        res = unzOpenCurrentFile(info.zipFileHandle); 
       } 
       if (UNZ_OK != res) 
       { 
        return false; 
       } 

       // read uncompressed data 
       int readResult = unzReadCurrentFile(info.zipFileHandle, block.Data(), info.uncompressedSize); 

       // close the file 
       res = unzCloseCurrentFile(info.zipFileHandle); 
       if (UNZ_OK != res) 
       { 
        return false; 
       } 

       if (info.uncompressedSize == readResult) 
       { 
        return ROBE_NEW MemoryFile(block.Data(), info.uncompressedSize); 
       } 
       else 
       { 
        return NULL; 
       } 
      } 
      else 
      { 
       return NULL; 
      } 
     } 

     IFile* ZipArchiveImpl::OpenRead(u32 id) 
     { 
      ASSERT0(mFileNames.size() > id); 
      if (IsExist(mFileNames[id])) 
      { 
       return OpenRead(mFileNames[id]); 
      } 
      else 
      { 
       return NULL; 
      } 
     } 

     void ZipArchiveImpl::FillMap() 
     { 
      s32 walkRes = unzGoToFirstFile(mUnzHandle); 
      unz_file_info info; 
      while (UNZ_OK == walkRes) 
      { 

       // get info about current file 
       char currentFileName[512]; 
       s32 fileInfoRes = unzGetCurrentFileInfo(mUnzHandle, &info, currentFileName, sizeof(currentFileName), 0, 0, 0, 0); 

       std::string name = std::string(currentFileName); 
       mFileNames.push_back(name); 
       InitInfo(name, &info); 
       walkRes = unzGoToNextFile(mUnzHandle); 

      } 
      OpenRead(0); 

      if (UNZ_END_OF_LIST_OF_FILE != walkRes) 
      { 

      } 
     } 

     void ZipArchiveImpl::InitInfo(const std::string& name, unz_file_info* info) 
     { 
      ZipFileInfo zfi; 
      mFileMap.insert(std::pair<std::string, ZipFileInfo>(name, zfi)); 
      mFileMap[name].zipFileHandle = mUnzHandle; 
      int res = unzGetFilePos(mFileMap[name].zipFileHandle, &mFileMap[name].filePosInfo); 

      mFileMap[name].uncompressedSize = info->uncompressed_size; 

      char lastsymbol = name[name.size() - 1]; 
      if (lastsymbol == '/' || lastsymbol == '\\') 
      { 
       mFileMap[name].type = ZFT_DIR; 
      } 
      else 
      { 
       mFileMap[name].type = ZFT_FILE; 
      } 
     } 


     ZipArchiveImpl::~ZipArchiveImpl() 
     { 
      if (mInited) 
      { 
       if (mUnzHandle) unzClose(mUnzHandle); 
       if (mZipHandle) zipClose(mZipHandle, 0); 
      } 
     } 

     bool ZipArchiveImpl::IsExist(const std::string& name) 
     { 
      return (mFileMap.find(name) != mFileMap.end()); 
     } 

     void ZipArchiveImpl::SaveFileToZip(const std::string& path, IFile* file) 
     { 
      const u32 DefaultFileAttribute = 32; 


      MemoryBlock block(1); 
      block.Resize(file->GetFileSize()); 
      file->Read(block.Data(), block.GetSizeInBytes()); 

      zip_fileinfo zinfo; 

      memset(&zinfo, 0, sizeof(zinfo)); 

      zinfo.internal_fa = 0; 
      zinfo.external_fa = DefaultFileAttribute; 

      ::boost::posix_time::ptime pt = ::boost::posix_time::from_time_t(time(0)); 
      std::tm ptm    = ::boost::posix_time::to_tm(pt); 

      zinfo.dosDate   = 0; 
      zinfo.tmz_date.tm_year = ptm.tm_year; 
      zinfo.tmz_date.tm_mon = ptm.tm_mon; 
      zinfo.tmz_date.tm_mday = ptm.tm_mday; 
      zinfo.tmz_date.tm_hour = ptm.tm_hour; 
      zinfo.tmz_date.tm_min = ptm.tm_min; 
      zinfo.tmz_date.tm_sec = ptm.tm_sec; 

      zipOpenNewFileInZip(mZipHandle, path.c_str(), &zinfo, 0, 0, 0, 0, 0, Z_DEFLATED, Z_BEST_SPEED); 
      zipWriteInFileInZip(mZipHandle, block.Data(), block.GetSizeInBytes()); 
      zipCloseFileInZip(mZipHandle); 
     } 

     unsigned long ZipArchiveImpl::GetFileAttributes(const std::string& filePath) 
     { 
      unsigned long attrib = 0; 
      #ifdef WIN32 
      attrib = ::GetFileAttributes(filePath.c_str()); 
      #else 
      struct stat path_stat; 
      if (::stat(filePath.c_str(), &path_stat) == 0) 
      { 
       attrib = path_stat.st_mode; 
      } 
      #endif 
      return attrib; 
     } 
+1

你能舉個例子嗎?我正在努力,但不能找到如何使用庫從內存緩衝區解壓縮的幫助 – rraallvv 2014-06-28 01:26:02

0

查看鏈接中的代碼,沒有明顯的方法來傳遞內存緩衝區。將你的內存緩衝區保存爲一個文件,將其解壓縮。

或者你可以實現你自己的zlib_filefunc_def變種,它在一塊內存上而不是文件上運行。我不認爲這很難做到。

+0

在ioa pi_mem.c他們已經完成了它。所以我可以使用unzOpen2函數和記憶功能。我發現這個註釋:/ *文件名的格式如下: * + *這可能不適用,其中內存地址長度大於int的 *大小因此可能需要尋址64位 *體系結構 * /所以現在我明白他們如何將它存儲在const char * filename中。 – DenSumy 2013-04-29 08:53:03

0

結帳minizip的nmoinvaz叉:要從內存使用fill_memory_filefunc一個zip文件解壓縮,並提供適當的ourmemory_t結構

zlib_filefunc_def filefunc32 = {0}; 
ourmemory_t unzmem = {0}; 

unzmem.size = bufsize; 
unzmem.base = (char *)malloc(unzmem.size); 
memcpy(unzmem.base, buffer, unzmem.size); 

fill_memory_filefunc(&filefunc32, &unzmem); 

unzOpen2("__notused__", &filefunc32); 
0

新增到unzip.c此功能

extern unzFile ZEXPORT unzOpenBuffer(const void* buffer, uLong size) 
{ 
    zlib_filefunc_def filefunc32 = { 0 }; 
    ourmemory_t *punzmem = (ourmemory_t*)malloc(sizeof(ourmemory_t)); 
    punzmem->size = size; 
    punzmem->base = (char *)malloc(punzmem->size); 
    memcpy(punzmem->base, buffer, punzmem->size); 
    punzmem->grow = 0; 
    punzmem->cur_offset = 0; 
    punzmem->limit = 0; 
    fill_memory_filefunc(&filefunc32, punzmem); 
    return unzOpen2(NULL, &filefunc32); 
}