Russian Qt Forum

Qt => Вопросы новичков => Тема начата: alik от Февраль 15, 2016, 21:49



Название: qt и zlib
Отправлено: alik от Февраль 15, 2016, 21:49
Добрый вечер!

Нужно распаковать данные, находящиеся в QByteArray.
Данные были сжаты библиотекой ZLib.

Самостоятельный поиск пока ясности не дал.
Кто то пишет что нужно использовать встроенные Qcompress QUncompress, кто то пишет, что подключать ZLib библиотеку, еще QuaZip и т.д.

Подскажите плиз как полегче преодолеть проблему!


Название: Re: qt и zlib
Отправлено: Old от Февраль 15, 2016, 21:53
QByteArray qUncompress(const QByteArray & data)


Название: Re: qt и zlib
Отправлено: alik от Февраль 15, 2016, 22:02
QByteArray qUncompress(const QByteArray & data)

Делаю так (нашел где то на форумах):

QByteArray aInCompBytes = buffer;
                QByteArray aInUnCompBytes;
                QByteArray aInCompBytesPlusLen;
                int currentCompressedLen = CompressedDataLen;
                int currentUnCompressedLen = RawDataLen;
                aInCompBytes.resize(currentCompressedLen);
                aInCompBytesPlusLen = aInCompBytes;
                aInCompBytesPlusLen.prepend(QByteArray::number(currentUnCompressedLen));
                aInUnCompBytes.resize(currentUnCompressedLen);
                aInUnCompBytes = qUncompress(aInCompBytesPlusLen);


Выходной буфер пустой! ((
Данные нерасжимаются


Название: Re: qt и zlib
Отправлено: Old от Февраль 15, 2016, 22:12
А как данные сжимались? Что там в исходном QByteArray?


Название: Re: qt и zlib
Отправлено: alik от Февраль 15, 2016, 22:16
а кто нибудь вообще имел дело с zlib сжатием в QT.
В Дельфи я подключал библиотеку ZLib и работал с данными.
Здесь я пока плохо ориентируюсь.
Может кто подскажет как подключить библиотеку.

В pro файле я записал:

INCLUDEPATH += ./Packing/zlib
LIBS  += ./Packing/zlib -llibz

Бибиотека zlib лежит у меня в подкаталоге Packing/zlib директории где сидит сам pro файл.
Правильно это или надо забросить эту библиотеку в директории, где записываются компилированные файлы, типа D:\Projects\QT\build-myprog-Desktop_Qt_5_2_0_MinGW_32bit-Debug ?


Название: Re: qt и zlib
Отправлено: alik от Февраль 15, 2016, 22:23
А как данные сжимались? Что там в исходном QByteArray?

Данные сжимались библиотекой ZLib в Delphi.
В начале пакета буфера находится:

"xÚì]\007wÛ:³ä9è\235\000\010\026\211¤º-w;É\227ûþÿ/{K¹ÆQ®Kl_¹À9:²£Ðärvvf\0010(\033\006Á\204r\215²\007\006Í\004#Ìå\g6jÎ\030e\031\t£²Z\036\237\234\255K\233eV;\025Ý\003\207ÁÙk\014B)Æ\230R.\005\227Êh!ùëü¢Ç\016Æ9åÞ\n$¥¤\224\021\201Åòl±Ü[̦ó\gÿñ Y\2062*¸à\214SL9%/zxôÄÏcÊ\224òR;¢2Ê\030Ó¢;ýþm=/c\014^*¡(Êvbà\227ÇïÓ®\214\010N\030gT²\034YÅ\004çÎõGÿü\w¥µ1Ä"¤rlv!N¯qÇ®\216É\036\0278Ä%|\210[Ëõ@\nÚú¶\235\034üøùmµ\030§d\213º\032\215'á?\217\025z\235X]\037}\003YüXti[b*\202ð\223¾\237ìÿ¼8_Ïæ}_\230¼(F^g\037t »È¥\217ME¬½\024~½Wï\2..."


Название: Re: qt и zlib
Отправлено: Swa от Февраль 16, 2016, 12:57
В pro файле я записал:

INCLUDEPATH += ./Packing/zlib
LIBS  += ./Packing/zlib -llibz

Бибиотека zlib лежит у меня в подкаталоге Packing/zlib директории где сидит сам pro файл.
Правильно это или надо забросить эту библиотеку в директории, где записываются компилированные файлы, типа D:\Projects\QT\build-myprog-Desktop_Qt_5_2_0_MinGW_32bit-Debug ?

Попробуй так:
Код:
LIBS  += -L$${_PRO_FILE_PWD_}/Packing/zlib
LIBS  += -llibz

А динамическая библиотека (.dll) должна быть в каталоге с exe файлом.


Название: Re: qt и zlib
Отправлено: sergek от Февраль 16, 2016, 21:09
Если данные сжаты zlib, а распаковать нужно qUncompress, то в заголовке нужно поменять порядок байтов, например, так:
Код:
QByteArray obj;
QByteArray pref=obj.left(4);
// сжатые данные (little-endian -> big-endian)
obj[0]=pref[3];
obj[1]=pref[2];
obj[2]=pref[1];
obj[3]=pref[0];
QByteArray deflate =  qUncompress(obj);
И наоборот, если жмете qCompress, а распаковываете с помощью zlib, то
Код:
QByteArray zip=qCompress(xml);
QByteArray pref=zip.left(4);
// big-endian -> little-endian
zip[0]=pref[3];
zip[1]=pref[2];
zip[2]=pref[1];
zip[3]=pref[0];


Название: Re: qt и zlib
Отправлено: alik от Февраль 17, 2016, 18:31
Если данные сжаты zlib, а распаковать нужно qUncompress, то в заголовке нужно поменять порядок байтов, например, так:
Код:
QByteArray obj;
QByteArray pref=obj.left(4);
// сжатые данные (little-endian -> big-endian)
obj[0]=pref[3];
obj[1]=pref[2];
obj[2]=pref[1];
obj[3]=pref[0];
QByteArray deflate =  qUncompress(obj);
И наоборот, если жмете qCompress, а распаковываете с помощью zlib, то
Код:
QByteArray zip=qCompress(xml);
QByteArray pref=zip.left(4);
// big-endian -> little-endian
zip[0]=pref[3];
zip[1]=pref[2];
zip[2]=pref[1];
zip[3]=pref[0];


Делаю так:


            buffer.resize(CompressedDataLen);
            in.readRawData(buffer.data(), buffer.size());  // считывание данных, сжатых библиотекой ZLib
            //---Расжатие данных---------------------------------------------------
            try
            {
                char pref[4];
                memcpy(&pref, &RawDataLen, 4);     // в pref записываю побайтно длину несжатых данных
               
                buffer.remove(0,4);                         // удаляю заголовок из данных сжатых библотекой ZLib
                buffer.insert(0, pref[3]);                   // вставляю длину несжатых данных
                buffer.insert(0, pref[2]);
                buffer.insert(0, pref[1]);
                buffer.insert(0, pref[0]);
                 
                QByteArray RawData;
                RawData = qUncompress(buffer);      // пытаюсь расжать данные

Результат RawData - пустой


Название: Re: qt и zlib
Отправлено: sergek от Февраль 17, 2016, 20:18
А как я предлагал, не пробовали?
Давайте минимальный проект с исходным массивом.


Название: Re: qt и zlib
Отправлено: alik от Февраль 18, 2016, 12:01
А как я предлагал, не пробовали?
Давайте минимальный проект с исходным массивом.


RawDataLen = 50
quint8 RawData[RawDataLen] = (0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5)

после сжатия массива RawData, получается следующий массив
CompressedDataLen = 24
quint8 CompressedData[CompressedDataLen] = (120, 218, 99, 96, 0, 1, 70, 24, 96, 66, 0, 102, 24, 96, 65, 0, 86, 32, 0, 0, 8, 52, 0, 123)
Первые 4 элемента (120, 218, 99, 96) похожи на стандартный заголовок

Вообщем распаковать даже такой простой массив CompressedData с помощью QUncompress пока не получается


Название: Re: qt и zlib
Отправлено: Vamireh от Февраль 18, 2016, 12:20
Что-то я тут запутался что надо и что не получается. Я наоборот разжимал на C# данные, сжатые qCompress'ом. Проблем не было, единственный нюанс - qCompress добавляет в начало 4 байта. Я их просто игнорировал. Наоборот, соответственно, их надо добавить. Осталось только понять, какие они должны быть.


Название: Re: qt и zlib
Отправлено: alik от Февраль 18, 2016, 12:47
            RawDataLen = 50;                                                                                                                                     // длина первичных данных
            CompressedDataLen = 24;                                                                                                                          // длина данных сжатых библиотекой Zlib
            unsigned char buf[24] = {120, 218, 99, 96, 0, 1, 70, 24, 96, 66, 0, 102, 24, 96, 65, 0, 86, 32, 0, 0, 8, 52, 0, 123};   // Данные сжатые библиотекой Zlib

            QByteArray CompressedData;
            CompressedData = QByteArray::fromRawData(reinterpret_cast<char*>(buf), 24);

            CompressedData.remove(0,4);

            char tmp[4];
            memcpy(&tmp, &RawDataLen, 4);
            CompressedData.insert(0, tmp[0]);
            CompressedData.insert(0, tmp[1]);
            CompressedData.insert(0, tmp[2]);
            CompressedData.insert(0, tmp[3]);
            RawData = qUncompress(CompressedData);

Результат тот же - RawData пустой


Название: Re: qt и zlib
Отправлено: sergek от Февраль 18, 2016, 13:42
Еще раз. Дайте компилябельный проект.
Сжатые данные у вас откуда берутся, из файла? Его тоже добавьте.
Что в архиве, знаете? И с чего взяли, что он сжат zlib?


Название: Re: qt и zlib
Отправлено: alik от Февраль 18, 2016, 14:29
Вот файл zlib_file.dat, сжатый стандартной библиотекой Zlib из дельфи
и сам проект. Путь к zlib_file.dat переукажите по факту.

Вот на всякий случай единственная функция проекта:

bool read_zlib(QString FileName)
{
    QFile file(FileName);
    if (!file.open(QIODevice::ReadOnly)) return false;

    QDataStream in(&file);
    int CompressedDataLen = file.size();   // = 24

    try
    {
            QByteArray CompressedData;
            CompressedData.resize(CompressedDataLen);
            in.readRawData(CompressedData.data(), CompressedData.size());
            //unsigned char buf[24] = {120, 218, 99, 96, 0, 1, 70, 24, 96, 66, 0, 102, 24, 96, 65, 0, 86, 32, 0, 0, 8, 52, 0, 123};
            //CompressedData = QByteArray::fromRawData(reinterpret_cast<char*>(buf), 24);


            //---Расжатие данных---------------------------------------------------
            int RawDataLen = 50;

            CompressedData.remove(0,4);

            char tmp[4];
            memcpy(&tmp, &RawDataLen, 4);
            CompressedData.insert(0, tmp[3]);
            CompressedData.insert(0, tmp[2]);
            CompressedData.insert(0, tmp[1]);
            CompressedData.insert(0, tmp[0]);

            QByteArray RawData;
            RawData = qUncompress(CompressedData);

            CompressedData.clear();
            RawData.clear();

            return true;
    }
    catch (std::exception & e)
    {
        goto finally;
    }
    finally:
    {
        in.~QDataStream();
        file.close();
    }
}


Название: Re: qt и zlib
Отправлено: alik от Февраль 18, 2016, 16:52
Ребята, а как вызвать правильно функцию -

ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
                                   const Bytef *source, uLong sourceLen));

из встроенной библиотеки #include <QtZlib/zlib.h>   ?

У меня есть буферы QByteArray, как мне перейти к ByteF ?

Можно писать что то типа ?
QByteArray Dest, Src;
uncompress(ByteF (Dest), CompressedDataLen, ByteF (Src), RawDataLen);



Название: Re: qt и zlib
Отправлено: alik от Февраль 18, 2016, 20:24
Все победил проблему, очень просто:

#include <QtZlib/zlib.h>

            unsigned char *compressBuf = new unsigned char[CompressedDataLen];
            memcpy(compressBuf, buffer, CompressedDataLen);
            unsigned char *uncompressBuf = new unsigned char[RawDataLen];
            unsigned long int compressBufLength = CompressedDataLen;
            unsigned long int uncompressLength = RawDataLen;
            int uncompressValue = uncompress(uncompressBuf, &uncompressLength, compressBuf, compressBufLength);

Результирующий буфер лежит в uncompressBuf !


Название: Re: qt и zlib
Отправлено: sergek от Февраль 18, 2016, 21:27
Цитировать
Note: If you want to use this function to uncompress external data that was compressed using zlib, you first need to prepend a four byte header to the byte array containing the data. The header must contain the expected length (in bytes) of the uncompressed data, expressed as an unsigned, big-endian, 32-bit integer.
Код:
    QFile file("./zlib_file.dat");
    if(!file.open(QIODevice::ReadOnly)){
        return;
    }
    QByteArray data = file.readAll();
    QByteArray head(4,0);
    head[3] = 255;
    data.insert(0,head);
    QByteArray deflate =  qUncompress(data);