CSimpleZipArchive
От: Gosha Украина  
Дата: 21.03.03 21:57
Оценка: 54 (7)
Всем привет!

Вот, понадобилось создавать zip-архивы с помощью библиотеки ZLib. Решил поделиться результатами своих изысканий, может кому и сгодится. Код приводится без всяких претензий на полноту и оригинальность, так... чтоб было с чего начать. Извиняюсь за "расширенную" индикацию ошибок в лице return false , если понадобится, дополнить труда не составит.

Пример использования:
#include "stdafx.h"
#include "SimpleZipArchive.h"

int main(int argc, char* argv[])
{
    CSimpleZipArchive zip("d:\\_myzip.zip");

    zip.AddFile("d:\\file1.txt");
    zip.AddFile("d:\\file2.doc");
    zip.AddFile("d:\\file3.xls");
    zip.RemoveFile("d:\\file2.doc");
    
    zip.ZipIt();

    return 0;
}

Сам класс:
#if !defined(_SIMPLEZIPARCHIVE_H_INCLUDED_)
#define _SIMPLEZIPARCHIVE_H_INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#pragma comment(lib, ".\\zlib\\zlib.lib")

#include ".\zlib\zip.h"
#include <sys/stat.h>
#include <time.h>
#include <map>
#include <string>
using namespace std;

#define READ_BUFFER_SIZE 65535


//Спасибо тов. Bell-у за наше счастливое детство :)
struct CaseInsensitiveLess : public binary_function<string, string, bool>
{
   bool operator()(const string &s1, const string &s2) const
   {
      return stricmp(s1.c_str(), s2.c_str()) < 0;
   }
};

typedef map<string, bool, CaseInsensitiveLess> STRCI_MAP;


class CSimpleZipArchive  
{
public:
    CSimpleZipArchive(const char* _zipName = NULL) {    SetZipFileName(_zipName);    }

    virtual ~CSimpleZipArchive() {}

    void SetZipFileName(const char* _zipName) 
    {
        if (_zipName && 0 != *_zipName)
            m_ZipFileName = _zipName;
    }

    const char* GetZipFileName() const {    return m_ZipFileName.c_str();    }

    bool RemoveFile(const char* _fileName)
    {        
        if (!_fileName || 0 == *_fileName) return false;
        STRCI_MAP::iterator findIter = m_Files.find(string(_fileName));
        if (findIter != m_Files.end())
        {
            m_Files.erase(findIter);
            return true;
        }
        else
            return false;
    }

    bool AddFile(const char* _fileName)
    {
        if (!_fileName || 0 == *_fileName) return false;
        pair<STRCI_MAP::iterator, bool> result =
            m_Files.insert(STRCI_MAP::value_type(string(_fileName), true));
        return result.second;
    }

    bool ZipIt() const
    {
        bool result = false;
        if ( 0 == m_Files.size()) return result;

        STRCI_MAP::const_iterator Iter = m_Files.begin();
        zipFile zipfile = zipOpen(m_ZipFileName.c_str(), 0);
        if (zipfile != NULL)
        {
            while (Iter != m_Files.end())
            {
                result = false;
                const char* srcFullFileName = Iter->first.c_str();
                const char* p = strrchr(srcFullFileName, '\\');
                const char* srcFileName = (NULL == p) ? srcFullFileName : p + 1;

                char read_buf[READ_BUFFER_SIZE];
                FILE* file = fopen(srcFullFileName, "rb");
                if (file != NULL)
                {
                    zip_fileinfo zfileinfo = {0};
                    struct _stat file_stat = {0};
                    _fstat(_fileno(file), &file_stat);
                    struct tm* file_time = localtime(&file_stat.st_mtime);
                    tm_zip* zip_time = &zfileinfo.tmz_date;
                    memcpy(zip_time, file_time, sizeof(tm_zip));

                    int compression = Z_BEST_COMPRESSION;
                    if ( ZIP_OK == zipOpenNewFileInZip(zipfile, srcFileName, 
                            &zfileinfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, compression))
                    {
                        while(!feof(file))
                        {
                            result = false;
                            size_t count = fread( read_buf, sizeof(char), READ_BUFFER_SIZE, file );
                            if(!ferror(file))
                            {
                                if ( ZIP_OK == zipWriteInFileInZip(zipfile, read_buf, count))
                                {
                                    result = true;
                                    continue;
                                }
                                else break;
                            }else break;
                        }
                        result = result && (Z_OK == zipCloseFileInZip(zipfile));
                    }
                    result = result && (0 == fclose(file));
                }
                (result) ? Iter++ : Iter = m_Files.end();
            }
            result = result && (Z_OK == zipClose(zipfile, NULL));
        }
        return result;
    }

private:
    STRCI_MAP    m_Files;
    string        m_ZipFileName;
};

#endif // !defined(_SIMPLEZIPARCHIVE_H_INCLUDED_)
RSDN@Home
Re: CSimpleZipArchive
От: Аноним  
Дата: 23.03.05 12:54
Оценка:
Кстати, вопрос в тему — как добавить в ZIP-архив пустую папку?
Re[2]: CSimpleZipArchive
От: Gosha Украина  
Дата: 24.03.05 14:37
Оценка: 36 (6)
Здравствуйте, Аноним, Вы писали:

А>Кстати, вопрос в тему — как добавить в ZIP-архив пустую папку?

Не, не знаю. Не нужно было, не разбирался.

PS.
Вот ведь время летит... Оригинальному посту уже два года (!!!) стукнуло. А вроде как вчера писал
Раз уж тема всплыла, кидаю код с распаковщиком. Чуток отличается от прежнего, переделывался под нужды одной из прог. Функционал по минимуму — простые архивы кушает, без папок. Но всяко лучше чем ничего, может кому и пригодится.

Packer.h
#pragma once

#include <vector>
#include <string>

typedef std::vector<std::string> STR_VEC;

struct CPacker
{
    //заархивировать файлы
    BOOL Pack(STR_VEC& _files, const char* _zipName);
    //разархивировать
    BOOL Unpack(const char* _zipName, const char* _dstFolder);
};

Packer.cpp
#include "StdAfx.h"
#include ".\packer.h"

#include ".\zlib\zip.h"
#include ".\zlib\unzip.h"
#include <sys/stat.h>
#include <time.h>

#pragma comment(lib, ".\\zlib\\zlib.lib")

#define READ_BUFFER_SIZE 65535

BOOL CPacker::Pack(std::vector<std::string>& _files, const char* _zipName)
{
    BOOL result = false;
    if ( 0 == _files.size()) 
        return result;

    STR_VEC::const_iterator Iter = _files.begin();
    zipFile zipfile = zipOpen(_zipName, 0);
    if (zipfile != NULL)
    {
        while (Iter != _files.end())
        {
            result = false;
            const char* srcFullFileName = Iter->c_str();
            const char* p = strrchr(srcFullFileName, '\\');
            const char* srcFileName = (NULL == p) ? srcFullFileName : p + 1;

            char read_buf[READ_BUFFER_SIZE];
            FILE* file = fopen(srcFullFileName, "rb");
            if (file != NULL)
            {
                zip_fileinfo zfileinfo = {0};
                struct _stat file_stat = {0};
                _fstat(_fileno(file), &file_stat);
                struct tm* file_time = localtime(&file_stat.st_mtime);
                tm_zip* zip_time = &zfileinfo.tmz_date;
                memcpy(zip_time, file_time, sizeof(tm_zip));

                int compression = Z_BEST_COMPRESSION;
                if ( ZIP_OK == zipOpenNewFileInZip(zipfile, srcFileName, 
                    &zfileinfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, compression))
                {
                    while(!feof(file))
                    {
                        result = false;
                        size_t count = fread( read_buf, sizeof(char), READ_BUFFER_SIZE, file );
                        if(!ferror(file))
                        {
                            if ( ZIP_OK == zipWriteInFileInZip(zipfile, read_buf, count))
                            {
                                result = true;
                                continue;
                            }
                            else 
                                break;
                        }else 
                            break;
                    }
                    result = result && (Z_OK == zipCloseFileInZip(zipfile));
                }
                result = result && (0 == fclose(file));
            }
            (result) ? Iter++ : Iter = _files.end();
        }
        result = result && (Z_OK == zipClose(zipfile, NULL));
    }
    return result;
}

BOOL CPacker::Unpack(const char* _zipName, const char* _dstFolder)
{
    BOOL result = FALSE;
    unzFile zipFile = unzOpen(_zipName);
    if (NULL != zipFile) 
    {
        if (UNZ_OK == unzGoToFirstFile(zipFile))
        {
            BOOL bContinue = TRUE;
            while (bContinue) 
            {
                result = FALSE;
                unz_file_info fi;
                char filename[MAX_PATH] = {0};
                if (UNZ_OK == unzGetCurrentFileInfo(zipFile, &fi, 
                    filename, sizeof(filename), 0, 0, 0, 0))
                {
                    if (UNZ_OK == unzOpenCurrentFile(zipFile))
                    {
                        UINT dataLen = fi.uncompressed_size;
                        BYTE* fileData = new BYTE[dataLen];
                        if (!fileData) 
                            break;
                        if(dataLen == unzReadCurrentFile(zipFile, fileData, dataLen))
                        {
                            char filePathName[MAX_PATH] = {0};
                            strcat(filePathName, _dstFolder);
                            strcat(filePathName, "\\");
                            strcat(filePathName, filename);
                            FILE* pFile = fopen(filePathName, "wb");
                            if (pFile)
                            {
                                result = (dataLen == fwrite(fileData, 1, dataLen, pFile));
                                result = result && (0 == fclose(pFile));
                            }
                        }
                        delete [] fileData;
                    }
                    result = result && (UNZ_OK == unzCloseCurrentFile(zipFile));
                }
                if (!result) 
                    break;
                if (UNZ_END_OF_LIST_OF_FILE == unzGoToNextFile(zipFile))
                    bContinue = FALSE;
            }
        }
        result = result && (UNZ_OK == unzClose(zipFile));
    }
    return result;
}
Re[3]: CSimpleZipArchive
От: DmitryElj Россия  
Дата: 09.11.05 07:37
Оценка:
А кстати, не сталкивался ли кто с такой проблемой — при добавлении файлов в ZIP-архив время, сохраненное в файле, сохраняется для некоторых из файлов (с вероятностью 1/10 прмерно)увеличенным на 1 секунду? Причем проблема проявляется только на дисках с NTFS, с FAT32 все нормально.

Заранее tnx.
Re[4]: CSimpleZipArchive
От: Аноним  
Дата: 09.11.05 09:30
Оценка:
Здравствуйте, DmitryElj, Вы писали:

DE>А кстати, не сталкивался ли кто с такой проблемой — при добавлении файлов в ZIP-архив время, сохраненное в файле, сохраняется для некоторых из файлов (с вероятностью 1/10 прмерно)увеличенным на 1 секунду? Причем проблема проявляется только на дисках с NTFS, с FAT32 все нормально.


DE>Заранее tnx.


В зипе хранится dostime, секунды в котором кодируются 5 битами, т.е. хранятся только "чётные" секунды. Нечётные округляются вверх.
Re[5]: CSimpleZipArchive
От: DmitryElj Россия  
Дата: 09.11.05 14:50
Оценка:
Здравствуйте, Аноним, Вы писали:

А>В зипе хранится dostime, секунды в котором кодируются 5 битами, т.е. хранятся только "чётные" секунды. Нечётные округляются вверх.


Я уже разобрался, и даже сам себе написал ответ: http://www.rsdn.ru/Forum/Message.aspx?mid=1478348&amp;only=1
Автор: DmitryElj
Дата: 09.11.05


В любом случае, спасибо.
Re[3]: CSimpleZipArchive + folders support
От: daisywheel Украина www.daisywheel.kiev.ua
Дата: 27.02.07 12:38
Оценка:
Оказалось что предложенный код не умеет работать с папками в архиве. Мой посильный вклад:
if (UNZ_OK == unzGetCurrentFileInfo(zip_file, &fi,
filename, sizeof(filename), 0, 0, 0, 0))
{
if(fi.uncompressed_size)//file
{
if (UNZ_OK == unzOpenCurrentFile(zip_file))
{
UINT data_len = fi.uncompressed_size;
BYTE* file_data = new BYTE[data_len];
if (!file_data)
break;
if(data_len == unzReadCurrentFile(zip_file, file_data, data_len))
{
char file_path_name[MAX_PATH] = {0};
strcat(file_path_name, i_dest_dir.c_str());
strcat(file_path_name, "\\");
strcat(file_path_name, filename);
FILE* pFile = fopen(file_path_name, "wb");
if (pFile)
{
result = (data_len == fwrite(file_data, 1, data_len, pFile));
result = result && (0 == fclose(pFile));
}
}
delete [] file_data;
}
result = result && (UNZ_OK == unzCloseCurrentFile(zip_file));
}
else//dir
{
std::string new_dir = i_dest_dir;
new_dir += "\\";
new_dir += filename;

_mkdir(new_dir.c_str());
result = true;
}
}
Здравствуйте, Gosha, Вы писали:

G>Здравствуйте, Аноним, Вы писали:


А>>Кстати, вопрос в тему — как добавить в ZIP-архив пустую папку?

G>Не, не знаю. Не нужно было, не разбирался.

G>PS.

G>Вот ведь время летит... Оригинальному посту уже два года (!!!) стукнуло. А вроде как вчера писал
G>Раз уж тема всплыла, кидаю код с распаковщиком. Чуток отличается от прежнего, переделывался под нужды одной из прог. Функционал по минимуму — простые архивы кушает, без папок. Но всяко лучше чем ничего, может кому и пригодится.

G>Packer.h

G>
G>#pragma once

G>#include <vector>
G>#include <string>

G>typedef std::vector<std::string> STR_VEC;

G>struct CPacker
G>{
G>    //заархивировать файлы
G>    BOOL Pack(STR_VEC& _files, const char* _zipName);
G>    //разархивировать
G>    BOOL Unpack(const char* _zipName, const char* _dstFolder);
G>};
G>

G>Packer.cpp
G>
G>#include "StdAfx.h"
G>#include ".\packer.h"

G>#include ".\zlib\zip.h"
G>#include ".\zlib\unzip.h"
G>#include <sys/stat.h>
G>#include <time.h>

G>#pragma comment(lib, ".\\zlib\\zlib.lib")

G>#define READ_BUFFER_SIZE 65535

G>BOOL CPacker::Pack(std::vector<std::string>& _files, const char* _zipName)
G>{
G>    BOOL result = false;
G>    if ( 0 == _files.size()) 
G>        return result;

G>    STR_VEC::const_iterator Iter = _files.begin();
G>    zipFile zipfile = zipOpen(_zipName, 0);
G>    if (zipfile != NULL)
G>    {
G>        while (Iter != _files.end())
G>        {
G>            result = false;
G>            const char* srcFullFileName = Iter->c_str();
G>            const char* p = strrchr(srcFullFileName, '\\');
G>            const char* srcFileName = (NULL == p) ? srcFullFileName : p + 1;

G>            char read_buf[READ_BUFFER_SIZE];
G>            FILE* file = fopen(srcFullFileName, "rb");
G>            if (file != NULL)
G>            {
G>                zip_fileinfo zfileinfo = {0};
G>                struct _stat file_stat = {0};
G>                _fstat(_fileno(file), &file_stat);
G>                struct tm* file_time = localtime(&file_stat.st_mtime);
G>                tm_zip* zip_time = &zfileinfo.tmz_date;
G>                memcpy(zip_time, file_time, sizeof(tm_zip));

G>                int compression = Z_BEST_COMPRESSION;
G>                if ( ZIP_OK == zipOpenNewFileInZip(zipfile, srcFileName, 
G>                    &zfileinfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, compression))
G>                {
G>                    while(!feof(file))
G>                    {
G>                        result = false;
G>                        size_t count = fread( read_buf, sizeof(char), READ_BUFFER_SIZE, file );
G>                        if(!ferror(file))
G>                        {
G>                            if ( ZIP_OK == zipWriteInFileInZip(zipfile, read_buf, count))
G>                            {
G>                                result = true;
G>                                continue;
G>                            }
G>                            else 
G>                                break;
G>                        }else 
G>                            break;
G>                    }
G>                    result = result && (Z_OK == zipCloseFileInZip(zipfile));
G>                }
G>                result = result && (0 == fclose(file));
G>            }
G>            (result) ? Iter++ : Iter = _files.end();
G>        }
G>        result = result && (Z_OK == zipClose(zipfile, NULL));
G>    }
G>    return result;
G>}

G>BOOL CPacker::Unpack(const char* _zipName, const char* _dstFolder)
G>{
G>    BOOL result = FALSE;
G>    unzFile zipFile = unzOpen(_zipName);
G>    if (NULL != zipFile) 
G>    {
G>        if (UNZ_OK == unzGoToFirstFile(zipFile))
G>        {
G>            BOOL bContinue = TRUE;
G>            while (bContinue) 
G>            {
G>                result = FALSE;
G>                unz_file_info fi;
G>                char filename[MAX_PATH] = {0};
G>                if (UNZ_OK == unzGetCurrentFileInfo(zipFile, &fi, 
G>                    filename, sizeof(filename), 0, 0, 0, 0))
G>                {
G>                    if (UNZ_OK == unzOpenCurrentFile(zipFile))
G>                    {
G>                        UINT dataLen = fi.uncompressed_size;
G>                        BYTE* fileData = new BYTE[dataLen];
G>                        if (!fileData) 
G>                            break;
G>                        if(dataLen == unzReadCurrentFile(zipFile, fileData, dataLen))
G>                        {
G>                            char filePathName[MAX_PATH] = {0};
G>                            strcat(filePathName, _dstFolder);
G>                            strcat(filePathName, "\\");
G>                            strcat(filePathName, filename);
G>                            FILE* pFile = fopen(filePathName, "wb");
G>                            if (pFile)
G>                            {
G>                                result = (dataLen == fwrite(fileData, 1, dataLen, pFile));
G>                                result = result && (0 == fclose(pFile));
G>                            }
G>                        }
G>                        delete [] fileData;
G>                    }
G>                    result = result && (UNZ_OK == unzCloseCurrentFile(zipFile));
G>                }
G>                if (!result) 
G>                    break;
G>                if (UNZ_END_OF_LIST_OF_FILE == unzGoToNextFile(zipFile))
G>                    bContinue = FALSE;
G>            }
G>        }
G>        result = result && (UNZ_OK == unzClose(zipFile));
G>    }
G>    return result;
G>}
G>


 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.