2012-01-10 20 views
6

Metin sıkıştırırken, gezegendeki diğer tüm uygulamalar (web uygulamaları dahil) arasında birlikte çalışabilirlik sağlamak istiyorum. QCompress ve qUncompress tahıllara karşı gözüktüğü için zlib'i doğrudan Qt uygulamasından kullanmaya çalışıyorum.Nasıl zlib bir QByteArray sıkıştırılır?

bana nasıl bir Qt uygulamasının dışında kullanılması, böylece YA qCompress çıktısını değiştirmek doğrudan QByteArray ile zlib kütüphanesini kullanmak gösterir basit (en az) cevabı kabul edecek

.

QByteArray tdata = QString("Oh noes!").toUtf8(); 
QByteArray cdata; 
uLongf len = 12 + 1.002*tdata.length(); 
compress(&cdata, &len, &tdata, tdata.length()); 

Ve hata:

Sonra

error: cannot convert 'QByteArray*' to 'Bytef*' for argument '1' to 'int compress(Bytef*, uLongf*, const Bytef*, uLong)'

Ben QByteArray :: constData()

compress(cdata.constData(), &len, &tdata, tdata.length()); 

kullanarak çalıştı Ama şu hata var

İşte benim utanç verici girişimi var:

error: invalid conversion from 'const char*' to 'Bytef*'

Bytef'ın ne olduğu hakkında hiçbir fikrim yok, dolayısıyla araştırmak için zlib kaynaklarına bakmaya başladım. Ama bunun için bulabilirsiniz tüm QtSources/src olduğu/3.taraf/zlib/zconf.h

# define Bytef     z_Bytef 

Yani şimdi ben sadece kayboldum.

+0

Eğer Boost iostreams kullanabilirsiniz: Bir zlib filtresi – akappa

cevap

6

çağırabilir, I) cdata.constData (kullanarak tahmin sorunu çözmek için yardımcı olur, ben oldukça kolay olduğunu düşünüyorum.

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.

Yani muhtemelen sadece bu gibi sıkıştırabiliriz:

I have no idea what a Bytef is so I start looking in the zlib sources to investigate.

Byte tanımları için:

Sadece
QByteArray tdata = QString("Oh noes!").toUtf8(); 
QByteArray compressedData = qCompress(tdata); 
compressedData.remove(0, 4); 
+0

Dedin "başına" var, ama kod eklemek yerine ilk 4 bayt kaldırır gibi görünüyor ön tarafa doğru. –

+1

Kod, demek istediğim şey. qUncompress, standart olmayan 4 baytın hazır olmasını bekler. Bu nedenle, qCompress standart olmayan 4 bayttan oluşmuş olmalıdır. QCompress'i kullanır ve bu baytları kaldırırsanız, yalnızca standart zlib öğelerine sahip olmanız gerekir. – cgmb

+0

Bunu zaten denedim. QUncompress kullandığımda (beklenen boyutu önceden tahmin ediyor) zlib bozuk olduğunu şikayet ediyor. –

0

Bir bayt dizisi için bir işaretçi, sıkıştırılacak bayt sayısı ve sıkıştırma düzeyi için bir işaretçi olarak girilen ve girdiyi sıkıştırmak için zlib kullanan bir kod yazdım. Sonuç bir dizgeye döndürülür.

enum compressionLevel 
{ 
    clFast, 
    clSmall, 
    clDefault 
}; 

const size_t ChunkSize = 262144; //256k default size for chunks fed to zlib 

void compressZlib(const char *s, size_t nbytes, std::string &out, compressionLevel l /*= clDefault*/) 
{ 
    int level = Z_DEFAULT_COMPRESSION; 
    switch (l) 
    { 
    case clDefault: 
     level = Z_DEFAULT_COMPRESSION; break; 
    case clSmall: 
     level = Z_BEST_COMPRESSION; break; 
    case clFast: 
     level = Z_BEST_SPEED; break; 
    }; 

    z_stream strm; 
    strm.zalloc = Z_NULL; 
    strm.zfree = Z_NULL; 
    strm.opaque = Z_NULL; 
    int ret = deflateInit(&strm, level); 
    if (ret != Z_OK) 
    { 
     throw std::runtime_error("Error while initializing zlib, error code "+ret); 
    } 
    size_t toCompress = nbytes; 
    char *readp = (char*)s; 
    size_t writeOffset = out.size(); 
    out.reserve((size_t)(nbytes * 0.7)); 
    while (toCompress > 0) 
    { 
     size_t toRead = std::min(toCompress,ChunkSize); 
     int flush = toRead < toCompress ? Z_NO_FLUSH : Z_FINISH; 
     strm.avail_in = toRead; 
     strm.next_in = (Bytef*)readp; 
     char *writep = new char[ChunkSize]; 
     do{ 
      strm.avail_out = ChunkSize; 
      strm.next_out = (Bytef*)writep; 
      deflate(&strm, flush); 
      size_t written = ChunkSize - strm.avail_out; 
      out.resize(out.size() + written); 
      memcpy(&(out[writeOffset]), writep, written); 
      writeOffset += written; 
     } while (strm.avail_out == 0); 
     delete[] writep; 
     readp += toRead; 
     toCompress -= toRead; 
    } 
    (void)deflateEnd(&strm); 
} 

Belki bu size doğrudan bu fonksiyonu qUncompress içinde this nota dayanarak

0

burada Sorunuzun son bölümü ile size yardım etmek ve Bytef, zconf.h'nin 332 ve 333 satırlarının yanı sıra 342:

332 #if !defined(__MACTYPES__) 
333 typedef unsigned char Byte; /* 8 bits */ 
... 
338 #ifdef SMALL_MEDIUM 
339  /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ 
340 # define Bytef Byte FAR 
341 #else 
342  typedef Byte FAR Bytef;  

FAR'un tanımı karışık mod MSDOS programlama içindir, aksi halde hiçbir şey olarak tanımlanmaz (zconf.h'nin 328-330 satırlarına bakın).

Böylece zlib Bytef typedefs ve Byte temelde en platformlarda unsigned char aynıdır.Aşağıdaki yapılacaklar nedenle mümkün olmalıdır:

QByteArray tdata = QString("Oh noes!").toUtf8(); 
QByteArray cdata(compressBound(tdata.length()), '\0'); 
uLongf len = compressBound(tdata.length()); 
compress(reinterpret_cast<unsigned char*>(cdata.data()), &len, 
     reinterpret_cast<unsigned char*>(tdata.data()), tdata.length()); 
+0

Bu kod, aşağıdakileri derleme başarısız: hata: 'char *' türünden geçersiz static_cast 'unsigned char *' yazarak ' –

+0

Tamam,' static_cast <>() 'yerine bir 'reinterpret_cast <>()' ... Bu kesinlikle derlemesi gerekir. – Jason

İlgili konular