2012-02-28 6 views
6

Io sto leggendo un file zippato con iostreams spinta: Il seguente funziona bene:È possibile potenziare gli iostream e leggere e comprimere i file compressi al volo?

namespace io = boost::iostreams; 
    io::filtering_istream in; 
    in.push(boost::iostreams::basic_gzip_decompressor<>()); 
    in.push(io::file_source("test.gz")); 
    stringstream ss; 
    copy(in, ss); 

Tuttavia, non si vuole prendere il colpo ricordo di leggere un intero file compresso con gzip nella memoria. Voglio essere in grado di leggere il file in modo incrementale.

Ad esempio, se ho una struttura di dati X che si inizializza da istream,

X x; 
x.read(in); 

fallisce. Presumibilmente questo è dovuto al fatto che potremmo dover inserire i caratteri nello stream se stiamo eseguendo stream parziali. Qualche idea se l'iostreams boost lo supporta?

+0

Would facendo un'operazione come chiamare 'getline()' 'quindi comprimere()' attraverso un lavoro di ciclo per voi? – user99545

+0

@ user99545: No: perché X si crea da dati binari. – ATemp

+0

Non vedo perché no. Ho usato boost iostreams per leggere e scrivere stream compressi con zlib in questo modo. – Ferruccio

risposta

1

Secondo lo iostream documentation il tipo boost::io::filtering_istream deriva da std::istream. Cioè, dovrebbe essere possibile passare questo ovunque sia previsto un std::istream&. Se si verificano errori in fase di esecuzione poiché è necessario specificare i caratteri unget() o putback(), è necessario dare un'occhiata al parametro pback_size che specifica il numero massimo di caratteri restituiti. Non ho visto nella documentazione quale sia il valore predefinito per questo parametro.

Se questo non risolve il problema, puoi descrivere qual è il tuo problema esattamente? Dal suo aspetto dovrebbe funzionare.

1

Penso che sia necessario scrivere il proprio filtro. Per esempio, per leggere un .tar.gz e di output i file contenuti, ho scritto qualcosa di simile

//using namespace std; 
namespace io = boost::iostreams; 

struct tar_expander 
{ 
    tar_expander() : out(0), status(header) 
    { 
    } 
    ~tar_expander() 
    { 
     delete out; 
    } 

    /* qualify filter */ 
    typedef char char_type; 
    struct category : 
     io::input_filter_tag, 
     io::multichar_tag 
    { }; 

    template<typename Source> 
    void fetch_n(Source& src, std::streamsize n = block_size) 
    { 
      /* my utility */ 
      .... 
    } 

    // Read up to n filtered characters into the buffer s, 
    // returning the number of characters read or -1 for EOF. 
    // Use src to access the unfiltered character sequence 
    template<typename Source> 
    std::streamsize read(Source& src, char* s, std::streamsize n) 
    { 
     fetch_n(src); 
     const tar_header &h = cast_buf<tar_header>(); 
     int r; 

     if (status == header) 
     { 
      ... 
     } 
     std::ofstream *out; 
     size_t fsize, stored; 

     static const size_t block_size = 512; 
     std::vector<char> buf; 

     enum { header, store_file, archive_end } status; 
    } 
} 

La mia funzione read(Source &...) quando viene chiamato riceve il testo decompresso. Per utilizzare il filtro:

ifstream file("/home/..../resample-1.8.1.tar.gz", ios_base::in | ios_base::binary); 
io::filtering_streambuf<io::input> in; 
in.push(tar_expander()); 
in.push(io::gzip_decompressor()); 
in.push(file); 
io::copy(in, cout); 
Problemi correlati