2014-02-21 48 views
1

我會很簡短:我有這樣一段代碼:壓縮/解壓縮的gzip到內存與提振

QByteArray MyNBT::decompressData(QByteArray data) 
{ 
    filtering_streambuf<input> in; 

    std::string _data = data.data(); 

    in.push(gzip_decompressor()); 
    in.push(boost::iostreams::back_inserter(_data)); 
    //in.push(std::back_inserter(_data)); 

    std::stringstream _sstream; 
    boost::iostreams::copy(in, _sstream); 

    QByteArray out = _sstream.rdbuf()->str().c_str(); 

    return out; 
} 

而且它在這條線(S)給出了一個錯誤:

in.push(boost::iostreams::back_inserter(_data)); 
//in.push(std::back_inserter(_data)); 

錯誤是:

/usr/include/boost/iostreams/chain.hpp:244: error: invalid application of 'sizeof' to incomplete type 'boost::STATIC_ASSERTION_FAILURE<false>' 
    BOOST_STATIC_ASSERT((is_convertible<category, Mode>::value)); 
    ^

的編譯器曾在std::back_inserter(_data)和兩次拋出這個錯誤有增強的一個。

在此先感謝。

回答

2

back_inserter是做什麼的?

確實。它將元素插入容器的後部。

然而,你似乎是一個front_readercontainer_source

好了,我沒有Qt的,但我用array_source,以適應您的輸入。(注意它是如何工作同樣好std::stringstd::vectorstd::array甚至只是const char []輸入)有運氣:

#include <fstream> 
#include <iostream> 

#include <boost/iostreams/filtering_stream.hpp> 
#include <boost/iostreams/filter/gzip.hpp> 
#include <boost/iostreams/copy.hpp> 
#include <sstream> 

int main() { 
    using namespace boost::iostreams; 
    filtering_streambuf<input> in; 

#if 0 
    std::string _data { 
#else 
    std::vector<char> _data { 
#endif 
     char(0x1f), char(0x8b), char(0x08), char(0x00), char(0xca), char(0xb5), 
     char(0x07), char(0x53), char(0x00), char(0x03), char(0xcb), char(0x48), 
     char(0xcd), char(0xc9), char(0xc9), char(0x57), char(0x28), char(0xcf), 
     char(0x2f), char(0xca), char(0x49), char(0xe1), char(0x02), char(0x00), 
     char(0x2d), char(0x3b), char(0x08), char(0xaf), char(0x0c), char(0x00), 
     char(0x00), char(0x00) 
    }; 

    in.push(gzip_decompressor()); 
    in.push(boost::iostreams::array_source(_data.data(), _data.size())); 

    std::stringstream _sstream; 
    boost::iostreams::copy(in, _sstream); 

    std::cout << _sstream.rdbuf(); 
} 

程序的輸出當然是hello world

+0

現在編譯,但它在拋出一個異常運行時'gzip錯誤'。我使用的gzip是可以的。我試過你的代碼,我製作的一些gzip(並用其他工作實例測試過)... – azteca1998

+0

我假設你現在指的是你的代碼,而不是我的(我測試過它)。我只能猜測,zip數據已損壞。也許你沒有使用二進制流或運行到終止NUL字符沿路 – sehe

+0

我的代碼讀取所有的二進制文件到一個字符串,它之間的一些函數(不改變它)之間傳遞,然後如果我把它標記爲壓縮,函數上面解壓縮它。非常簡單。 – azteca1998

0

修復它使用@sehe的答案。

下面是生成的代碼:(希望它會用同樣的錯誤的人是有用的)

QByteArray MyNBT::decompressData(QByteArray data) 
{ 
    filtering_streambuf<input> in; 

    std::vector<char> _data; 
    foreach(char ch, data) 
     _data.push_back(ch); 

    in.push(gzip_decompressor()); 
    in.push(boost::iostreams::array_source(_data.data(), _data.size())); 

    QByteArray out; 
    while (in.sgetc() != -1) 
     out += (unsigned char)in.sbumpc(); 

    std::cout << "out size! :: " << in.in_avail() << std::endl; 
    //std::cout << "out size! :: " << _sstream.str().size() << std::endl; 
    std::cout << "out size! :: " << out.size() << std::endl; 

    return out; 
} 
+0

看一看'std :: copy_n'會多麼更有效率,甚至可以使用'std :: vector const _data(data.begin(),data.end());'(注意const),你應該可以使用'std :: vector const _data(data.data(),data.size());'最後,爲什麼不直接使用'array_source(data.data(),data.size())'而不進行復制? – sehe

0

我也用一個簡單的字符數組,而對於效率的緣故不希望有創建矢量並複製緩衝區內容。所以,這是我對這項解壓縮或者直接從線讀取到另一個字符數組的字符數組壓縮一個簡單的在RAM壓縮/解壓縮實用程序類:

/* 
* GzipUtil.h 
* 
* Created on: Nov 3, 2015 
*  Author: tprice 
*/ 

#ifndef GZIPUTIL_H_ 
#define GZIPUTIL_H_ 

#include <unistd.h> 
#include <stdint.h> 
#include <vector> 
#include <stdlib.h> 

#include <boost/iostreams/filtering_stream.hpp> 
#include <boost/iostreams/filter/gzip.hpp> 

namespace BIO = boost::iostreams; 

class GzipUtil { 
public: 
GzipUtil() {} 
virtual ~GzipUtil() {} 

static ssize_t compress(char *src, char *dest, ssize_t len) 
{ 
    ssize_t retval = 0; 

    BIO::filtering_streambuf<BIO::input> in; 
    in.push(BIO::gzip_compressor()); 
    in.push(BIO::array_source(src, len)); 
    for(retval = 0; in.sgetc() != -1; retval++) 
    { 
     dest[retval] = (char) in.sbumpc(); 
    } 

    return retval; 
} 

static ssize_t decompress(char *src, ssize_t srclen, std::vector<char*> & dest, ssize_t destChunkLen) 
{ 
    ssize_t retval = 0; 
    char* chunkPtr = NULL; 
    ssize_t chunkUsed = 0; 

    BIO::filtering_streambuf<BIO::input> in; 
    in.push(BIO::gzip_decompressor()); 
    in.push(BIO::array_source(src, srclen)); 
    for(retval = 0; in.sgetc() != -1; retval++) 
    { 
     if((chunkPtr == NULL) || (chunkUsed >= destChunkLen)) 
     { 
      chunkPtr = (char*) malloc(destChunkLen); 
      dest.push_back(chunkPtr); 
      chunkUsed = 0; 
     } 
     chunkPtr[chunkUsed++] = (char) in.sbumpc(); 
    } 

    return retval; 
} 

}; 


#endif /* GZIPUTIL_H_ */