简体   繁体   中英

gzip compressed file streams in C++

My loader looks like that:

void LispAna::loadF() {
    formatives.rehash(2991);
    std::ifstream fin("data.txt");
    formCondition st;

    std::string key;
    std::string tmp;
    int itmp;

    for (std::string row; getline(fin, row, '\n');) {
        //"a\t0\txx\tA\n"
        std::istringstream ss(row);

        getline(ss, key, '\t');

        //pos
        getline(ss, tmp, '\t');
        st.pos = *(tmp.c_str());

        //types
        getline(ss, tmp, '\t');
        st.types = tmp;

        //condition
        getline(ss, tmp, '\t');
        st.condition = tmp;

        //if(ok)?
        formatives.insert(std::pair<std::string, formCondition>(key, st));
    }
}

Id like to replace std::ifstream witch own made zifstream . That can easily used for reading zlib compressed text files.

zifstream fin("data.txt.gz");
//..
for (std::string row; getline(fin, row, '\n');) {
//..
}

I have tinfl.c v1.11. And I dont have a clue witch class to extend and what functions to implement to achieve that. I dont need seek. Just simple linear reading and some basic error checking. Don't even need full header support, data files are own made.

First, I think Boost already has what you are looking for. If you can use it, it would certainly be simpler than rewriting the code yourself.

Otherwise: you'll need to define a filtering streambuf which does the compression, and forwards the compressed data on to another streambuf (almost certainly a filebuf opened in binary mode). Just derive from std::streambuf , with a pointer to the final target streambuf in your class. At the least, you'll have to overwrite the function overflow ; you might want to override xsputn as well.

The actual zifstream is then very simple: something like:

class zifstream : private std::filebuf, private zistreambuf, public std::istream
{
public:
    zifstream( std::string const& filename )
        : std::filebuf( filename.c_str(), std::ios_base::in | std::ios_base::binary )
        , zistreambuf( static_cast<std::filebuf>( this ) )
        , std::istream( static_cast<zistreambuf>( this ) )
    {
    }
};

is likely sufficient. (The standard classes which derive from std::istream also provide a rdbuf function which hides the one in the base class, and returns the derived type. This is more a "nice to have", in a few particular cases, and not really necessary.)

Note that if you're reading using locales other than "C" , you'll have to do the code translation in the filtering buffer; doing it in the filebuf will not work. (Again, Boost has the necessary support.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM