2012-02-28 16 views
6

Tôi đang đọc một tập tin đã giải nén sử dụng iostreams tăng: Sau đây hoạt động tốt:Có thể tăng cường iostreams đọc và nén các tệp được nén trên máy bay không?

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); 

Tuy nhiên, tôi không muốn để có những hit ký ức về đọc toàn bộ tập tin đã giải nén vào bộ nhớ. Tôi muốn có thể đọc tập tin theo từng bước.

Ví dụ, nếu tôi có một cấu trúc dữ liệu X khởi thân từ istream,

X x; 
x.read(in); 

thất bại. Có lẽ điều này là bởi vì chúng tôi có thể phải đặt lại các ký tự vào dòng nếu chúng tôi đang thực hiện một phần luồng. Bất kỳ ý tưởng cho dù tăng iostreams hỗ trợ này?

+0

Sẽ thực hiện một thao tác như gọi 'getline()' sau đó 'nén()' qua vòng lặp hoạt động cho bạn? – user99545

+0

@ user99545: Không: vì X tự tạo từ dữ liệu nhị phân. – ATemp

+0

Tôi không hiểu tại sao không. Tôi đã sử dụng tăng cường iostreams để đọc và viết các luồng nén zlib theo cách này. – Ferruccio

Trả lời

1

Theo số iostream documentation loại boost::io::filtering_istream có nguồn gốc từ std::istream. Đó là, nó sẽ có thể vượt qua điều này ở khắp mọi nơi một std::istream& dự kiến. Nếu bạn gặp lỗi tại thời gian chạy vì bạn cần phải có các ký tự unget() hoặc putback(), bạn nên xem thông số pback_size chỉ định số lượng ký tự trả về nhiều nhất. Tôi đã không nhìn thấy trong tài liệu những gì giá trị mặc định cho tham số này là.

Nếu cách này không giải quyết được sự cố của bạn, bạn có thể mô tả chính xác vấn đề của mình không? Từ vẻ ngoài của nó sẽ làm việc.

1

Tôi nghĩ bạn cần viết bộ lọc của riêng mình. Ví dụ, để đọc một .tar.gz và đầu ra các tập tin chứa, tôi đã viết một cái gì đó giống như

//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; 
    } 
} 

chức năng My read(Source &...) khi gọi nhận được văn bản đã được giải nén. Để sử dụng bộ lọc:

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);