crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )


  Ответ в ZIP архив создать программно как ?
Введите ваше имя
Подтвердите код

Введите в поле код из 6 символов, отображенных в виде изображения. Если вы не можете прочитать код с изображения, нажмите на изображение для генерации нового кода.
 

Опции сообщения
 Включить смайлы?
Иконки сообщения
(Опционально)
                                
                                
  [ Без иконки ]
 


Последние 10 сообщений [ в обратном порядке ]
SABROG Дата 12.10.2009, 15:19
  Плохо это решение тем, что оно не переносимо, ибо этот Wizard dll API зависим в то время как внутренние вызовы самой библиотеки InfoZip переносимы. Т.е., чтобы понять как это работает и правильно написать код, надо сначала переписать Wizard dll на обычном C++ с использованием STL или обычном Си. Потом уже этот код использовать в Qt.
filinGUI Дата 12.10.2009, 15:11
 
Цитата(SABROG @ 12.10.2009, 15:30) *
Найти бы еще пример как это делать. Мои копания примеров этой утилиты привели только к одному заключению - функций типа createZip()/Unzip() нет. Т.е. нужно делать какие-то подготовительные телодвижения, логика которых не становится понятной глядя на код.


Таких простых функций действительно нет, для упаковки используется последовательность вызовов ZpInit / ZpSetOptions / ZpArchive, для распаковки вызывается Wiz_SingleEntryUnzip. Для своего проекта я написал функцию SimpleUnzip (Qt3, библиотека Unzip.dll загружается динамически)
Раскрывающийся текст
//---------------------------------------------------------------------------
//  Служебные функции для SimpleUnzip
//---------------------------------------------------------------------------
int WINAPI DummyPrint(LPSTR, unsigned long) {return 0;}
int WINAPI DummyReplace(LPSTR) {return 0;}
int WINAPI DummyPassword(LPSTR, int, LPCSTR, LPCSTR) {return 0;}
void WINAPI DummyMessage(unsigned long, unsigned long, unsigned,
    unsigned, unsigned, unsigned, unsigned, unsigned,
    char, LPSTR, LPSTR, unsigned long, char) {}

//---------------------------------------------------------------------------
//  Распаковывает zip-архив a_zip в каталог a_dir, заменяя существующие файлы
//---------------------------------------------------------------------------
typedef int (WINAPI * FSINGLEENTRYUNZIP)( int, char **, int, char **,
                                          LPDCL, LPUSERFUNCTIONS );
bool SimpleUnzip( const QString& a_zip, const QString& a_dir )
{
    const QString noZip = ru( "Обработка архивов zip невозможна." );
    const QString errCap = ru("Ошибка");
    const TCHAR* UNZ_DLL_NAME = TEXT("unzip32.dll");
    TCHAR szFullPath[_MAX_PATH];
    TCHAR* ptr;
    if ( SearchPathW( 0, UNZ_DLL_NAME, 0,
                      sizeof(szFullPath) / sizeof(szFullPath[ 0 ]),
                      szFullPath, &ptr ) == 0 )
    {
        mbE( errCap, ru("Не найдена библиотека unzip32.dll.\n" + noZip ) );
        return false;
    }

    HMODULE hUnzipDll = LoadLibraryW( UNZ_DLL_NAME );
    if ( hUnzipDll == 0 )
    {
        mbE( errCap, ru("Не удалось загрузить библиотеку unzip32.dll.\n" + noZip ) );
        return false;
    }

    FSINGLEENTRYUNZIP pWiz_SingleEntryUnzip = (FSINGLEENTRYUNZIP)GetProcAddress(
        hUnzipDll, "Wiz_SingleEntryUnzip" );
    if ( pWiz_SingleEntryUnzip == 0 )
    {
        FreeLibrary( hUnzipDll );
        mbE( errCap, ru("Неправильная библиотека unzip32.dll.\n" + noZip ) );
        return false;
    }

    LPDCL lpDCL = new DCL;
    LPUSERFUNCTIONS lpUserFunctions = new USERFUNCTIONS;

    lpUserFunctions->password = DummyPassword;
    lpUserFunctions->print = DummyPrint;
    lpUserFunctions->replace = DummyReplace;
    lpUserFunctions->SendApplicationMessage = DummyMessage;
    lpUserFunctions->sound = 0;
    lpUserFunctions->ServCallBk = 0;

    //set up the flags to be passed into the dll.
    lpDCL->ExtractOnlyNewer = 0;  // Do not extract only newer
    lpDCL->SpaceToUnderscore = 0;
    lpDCL->PromptToOverwrite = 0; // "Overwrite all" selected, no query mode
    lpDCL->fQuiet = 2; // 0 = all messages, 1 = fewer messages, 2 = no messages
    lpDCL->ncflag = 0; // Write to stdout if true
    lpDCL->ntflag = 0; // Do not test zip file
    lpDCL->nvflag = 0; // Do not give a verbose listing
    lpDCL->nfflag = 0; // Do not freshen existing files only
    lpDCL->nzflag = 0; // display a zip file comment if true
    lpDCL->ndflag = 1; // Recreate directories != 0, skip "../" if < 2
    lpDCL->noflag = 1; // Over-write all files
    lpDCL->naflag = 0; // Do not convert CR to CRLF
    lpDCL->nZIflag = 0;// Do not get ZipInfo
    lpDCL->C_flag = 1; // Do not be case insensitive
    lpDCL->fPrivilege = 0;  // 1 => restore ACLs in user mode,
                        // 2 => try to use privileges for restoring ACLs

    QCString zip = a_zip.local8Bit();
    QCString dir = a_dir.local8Bit();
    lpDCL->lpszZipFN = const_cast<CHAR*>(static_cast<const char*>(zip));
    if ( a_dir.isEmpty() )
        lpDCL->lpszExtractDir = 0;
    else
        lpDCL->lpszExtractDir = const_cast<CHAR*>(static_cast<const char*>(dir));

//    qDebug( "zip=%s, dir=%s", lpDCL->lpszZipFN, lpDCL->lpszExtractDir );
    int res = pWiz_SingleEntryUnzip( 0, 0, 0, 0, lpDCL, lpUserFunctions );
//    qDebug( "unzip retcode=%d", res );
    bool rc = res == 0;

    delete lpDCL;
    delete lpUserFunctions;
    FreeLibrary( hUnzipDll );

    return rc;
}


Могу дать ещё пример SimpleZip для упаковки, но только на Delphi
SABROG Дата 12.10.2009, 14:30
 
Цитата(filinGUI @ 12.10.2009, 15:11) *
flankerr

Архивирование с вложенными каталогами и отображением прогресса можно сделать, используя Info-ZIP. Архив получается вполне стандартный и распакуется везде. Надо только собрать zip и unzip как dll и написать callback-функцию для отображения прогресса.


Найти бы еще пример как это делать. Мои копания примеров этой утилиты привели только к одному заключению - функций типа createZip()/Unzip() нет. Т.е. нужно делать какие-то подготовительные телодвижения, логика которых не становится понятной глядя на код.
filinGUI Дата 12.10.2009, 14:11
  flankerr

Архивирование с вложенными каталогами и отображением прогресса можно сделать, используя Info-ZIP. Архив получается вполне стандартный и распакуется везде. Надо только собрать zip и unzip как dll и написать callback-функцию для отображения прогресса.
kwisp Дата 12.10.2009, 8:23
  kuzulis,
первый пост об этом говорит.
kuzulis Дата 12.10.2009, 8:13
  А почему автору нельзя использовать сторонние архиваторы?

Проще, ИМХО, через QProcess их вызывать и в опциях командной строки подсовывать нужные каталоги для сжатия...

Для этого в самой программе автора определять - какие из архиваторов находятся в системе... НЕ ? :)
BRE Дата 11.10.2009, 12:46
 
Цитата(Litkevich Yuriy @ 11.10.2009, 13:33) *
в KDE в большенстве случаев индикатор выполнения болтается туда-сюда.

Если писать свой враппер, то это можно сделать как надо:
* Открыть архив
* Найти по имени файла его индекс
* Получить информацию о файле по индексу (необходим размер распакованных данных)
* В цикле читаем данные файла из архива кусками и посылаем сигнал о прогрессе.
Litkevich Yuriy Дата 11.10.2009, 12:33
  в KDE в большенстве случаев индикатор выполнения болтается туда-сюда.
BRE Дата 11.10.2009, 12:25
  Можно посмотреть решение в KDE. Там правда все сделано глобально, т.е. есть целая иерархия классов начиная с KArchive. У него есть наследник KZip.
Или посмотреть на библиотеку libzip. Она сишная, но можно самому написать враппер для C++ со всем необходимым функционалом.
Также вроде есть готовый враппер libzipios++.
SABROG Дата 9.10.2009, 23:39
 
Цитата(Litkevich Yuriy @ 9.10.2009, 19:28) *
Однако исодники у них открыты, или я ошибаюсь?

Открыты, только тогда придеться брать исходники p7zip (порт под linux). Там вроде бы какраз есть директория zip с исходниками. Думаю там точно такая же канитель будет с пониманием ABI, как и в InfoZip.
Просмотр темы полностью (откроется в новом окне)
RSS Текстовая версия Сейчас: 27.4.2024, 15:08