Распаковка gzip и IDataFilter
От: Аноним  
Дата: 19.10.06 12:48
Оценка:
Кто пользовался интерфейсами :

IEncodingFilterFactory
IDataFilter

для распаковки gzip архивов в винде, в частности интнресует и распаковка средствами винды потока данных
при работе с ftp сервером в MODE Z.
Re: Распаковка gzip и IDataFilter
От: CKBO3HRK  
Дата: 08.01.07 18:48
Оценка: 12 (2)
Здравствуйте, Аноним, Вы писали:

А>Кто пользовался интерфейсами :


А>IEncodingFilterFactory

А>IDataFilter

А>для распаковки gzip архивов в винде, в частности интнресует и распаковка средствами винды потока данных

А> при работе с ftp сервером в MODE Z.

пример работы с IEncodingFilterFactory и IDataFilter
Re: Распаковка gzip и IDataFilter
От: Аноним  
Дата: 18.05.07 06:30
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Кто пользовался интерфейсами :


А>IEncodingFilterFactory

А>IDataFilter

А>для распаковки gzip архивов в винде, в частности интнресует и распаковка средствами винды потока данных

А> при работе с ftp сервером в MODE Z.

Я так понял, что распаковка у вас получилась.
А что на счет запаковки
У меня что-то не получается ...

    CComPtr<IEncodingFilterFactory> pEFF;
    HRESULT hr = pEFF.CoCreateInstance(CLSID_StdEncodingFilterFac);
    CComPtr<IDataFilter> pDF;
    //accquire suitable filter
    if (!pEFF || FAILED(pEFF->GetDefaultFilter( L"text", L"gzip", &pDF))) return false;

    //temporary out buffers
    BYTE  outBuff[16384] = {0};
    DWORD dwOutBuffSize = sizeof(outBuff);

    long dwRead = 0, dwWritten = 0;
    char *Data = "здравствуй, супер архиватор, от славной фирмы microsoft";

    //encode chunk of data
    hr = pDF->DoEncode( 0, strlen(Data), Data,
                        dwOutBuffSize, (BYTE*)outBuff,
                        strlen(Data), &dwRead, &dwWritten, 0);

Код отрабатывается без ошибок, но dwWritten всегда равно 10
При любом содержимом char *Data, хотя dwRead всегда равно strlen(Data).
Re[2]: Распаковка gzip и IDataFilter
От: Аноним  
Дата: 19.05.07 14:45
Оценка: 6 (1)
Здравствуйте, Аноним, Вы писали:

А> Код отрабатывается без ошибок, но dwWritten всегда равно 10

А> При любом содержимом char *Data, хотя dwRead всегда равно strlen(Data).
А>

Есть такие грабельки (точнее особенность работы), внутри DoEncode происходит накапливание данных в свой буфер и очевидно она возвращает не все данные, а только часть (в данном случае 10 байт — заголовок gzip архива). Сделано это потому что сжатие может происходить на уровне битов и естественно не понятно как вернуть в буфер результат например в 50 битов длиной. Если же вам надо финализировать архив, то функция добавляет свой маркер конца архива и выравнивает это хозяйство до кратного 8 битам размера. Это ответ почему так происходит. Теперь ответ на вопрос "что делать?". Вызвать DoEncode ещё раз, но в качестве длины входных данных передать 0. Ну и зная что кусочек кода ценится выше всяких объяснений, вот функция распаковки gzip архива которая работает нормально:



BOOL WINAPI DecompressFile(HANDLE hArchFile, HANDLE hPlainFile)
{
    HRESULT rc;
    IEncodingFilterFactory* pEflt=NULL;
    IDataFilter* pDF=NULL;
    BOOL bOK=TRUE;
    rc = CoCreateInstance( CLSID_StdEncodingFilterFac, NULL, CLSCTX_INPROC_SERVER, IID_IEncodingFilterFactory, (LPVOID *) &pEflt);
        if( FAILED(rc) )
         return FALSE;
    pEflt->GetDefaultFilter(_T("gzip"), _T("text"), &pDF);
    if (pDF)
    {
            BYTE in_buff[32768]; 
        BYTE out_buff[32768];
        DWORD rdd=0;
        DWORD wrt=0;
        LONG proc=0;
        LONG outpt=0;
        __int64 filesize=0;
        __int64 processed=0;
        GetFileSizeEx(hArchFile, (PLARGE_INTEGER)&filesize);
        while (processed<filesize)
        {
            SetFilePointerEx(hArchFile, *((PLARGE_INTEGER)&processed), NULL, FILE_BEGIN);
            ReadFile(hArchFile, in_buff, sizeof(in_buff), &rdd, NULL);
            rc=pDF->DoDecode(0, sizeof(in_buff), in_buff, sizeof(out_buff), out_buff, rdd, &proc, &outpt, 0);
            if (FAILED(rc))
            {
                bOK=FALSE;
                break;
            }
            WriteFile(hPlainFile, out_buff, outpt, &wrt, NULL);
            processed+=proc;
        }
        do
        {
            rc=pDF->DoDecode(0, sizeof(in_buff), in_buff, sizeof(out_buff), out_buff, 0, &proc, &outpt, 0);
            if (FAILED(rc))
            {
                bOK=FALSE;
                break;
            }
            WriteFile(hPlainFile, out_buff, outpt, &wrt, 0);
        }while(outpt>0);
        pDF->Release();
        pEflt->Release();
        return bOK;
    }
    pEflt->Release();
    return FALSE;
}
Re[3]: Распаковка gzip и IDataFilter
От: Аноним  
Дата: 23.07.07 15:48
Оценка:
Нельзя ли еще привести пример СompressFile(HANDLE hPlainFile, HANDLE hArchFile) ?
Я таки ж не пониманимаю, что делать с не до конца законченным выходным буфером. Если я пакую большой файл частями: читаю данные во входной буфер, делаю Encode, вижу, что в выходном буфере есть данные для записи, пишу их в файл, читаю во входной буфер еще раз и тут вопрос — как мне вызывать метод Encode, чтобы он продолжил паковать к уже накопленным данным? Сдвигать, что-ли, начало выходного буфера на еще не занятую область и уменьшать его доступный размер?
Re[4]: Распаковка gzip и IDataFilter
От: Аноним  
Дата: 24.07.07 15:30
Оценка:
Отвечаю себе сам
Оказывается код компрессирования довольно похож.

bool CompressFile(const TCHAR* pszInFile, const TCHAR* pszOutFile)
{
//create decoding object instance
CComPtr<IEncodingFilterFactory> pEFF;
bool bOK = false;
HRESULT hr = pEFF.CoCreateInstance(CLSID_StdEncodingFilterFac);
CComPtr<IDataFilter> pDF;
//accquire suitable filter
if (!pEFF || FAILED(pEFF->GetDefaultFilter(L"gzip", L"text", &pDF))) {
return false;
}
if (pDF)
{
BYTE in_buff[32768];
BYTE out_buff[32768];
DWORD rdd=0;
DWORD wrt=0;
LONG proc=0;
LONG outpt=0;
__int64 filesize=0;
__int64 processed=0;

//open input file
HANDLE hArchFile = CreateFile(pszInFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hArchFile == INVALID_HANDLE_VALUE) {
return false;
}
//create output file
HANDLE hPlainFile = CreateFile(pszOutFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (hPlainFile == INVALID_HANDLE_VALUE) {
CloseHandle(hPlainFile);
return false;
}

GetFileSizeEx(hArchFile, (PLARGE_INTEGER)&filesize);
while (processed<filesize)
{
SetFilePointerEx(hArchFile, *((PLARGE_INTEGER)&processed), NULL, FILE_BEGIN);
ReadFile(hArchFile, in_buff, sizeof(in_buff), &rdd, NULL);
hr=pDF->DoEncode(0, sizeof(in_buff), in_buff, sizeof(out_buff), out_buff, rdd, &proc, &outpt, 0);
if (FAILED(hr))
{
bOK=false;
break;
}
WriteFile(hPlainFile, out_buff, outpt, &wrt, NULL);
processed+=proc;
}
do
{
hr=pDF->DoEncode(0, sizeof(in_buff), in_buff, sizeof(out_buff), out_buff, 0, &proc, &outpt, 0);
if (FAILED(hr))
{
bOK=false;
break;
}
WriteFile(hPlainFile, out_buff, outpt, &wrt, 0);
}while(outpt>0);
//close in/out file handles
CloseHandle(hArchFile);
CloseHandle(hPlainFile);
return bOK;
}
return FALSE;
}
Re[5]: Распаковка gzip и IDataFilter
От: Аноним  
Дата: 29.10.07 13:35
Оценка:
поставил IE7 вместо IE6 и компрессирование перестало работать. DoEncode возвращает "not implemented". DoDecode работает, по-прежнему. Получается, что MS выкинул компрессирование (платформа WinXP)?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.