Reputation: 530
I'm working on a project that requires reading from files. Those files can be uncompressed or compressed (.gz extension).
I've managed to set my project to exploit zlib and boost::iostreams to perform the uncompression, but I cannot properly handle the uncompressed files in form of std::istream.
Let me be more clear: the method I'm writing has the path to the file as input, and the logic that reads the file is done on std::ifstream object type. If the file is uncompressed one I'm ok, but the problem arises when it is compressed. Following online documentation from boost website, I'm doing something like this
//Read from the first command line argument, assume it's gzipped
std::ifstream file(filename, std::ios_base::in | std::ios_base::binary);
boost::iostreams::filtering_streambuf<boost::iostreams::input> inbuf;
inbuf.push(boost::iostreams::gzip_decompressor());
inbuf.push(file);
//Convert streambuf to istream
std::istream instream(&inbuf);
The problem is that I want to have a std::ifstream
for the uncompressed file, but the only way in which I can get the uncompressed file is in form of std::istream
(last line of the snippet). Because my handling logic is expecting std::ifstream, I am trying to figure out how I can get an ifstream from the istream, but so far I've found no useful resources to start with.
Rewriting logic to handle different input type is not the goal that I want, so I'm asking you if you have any hint on the topic.
Any help/resource appreciated!
Thanks
Upvotes: 1
Views: 1940
Reputation: 392911
If you need a filestream, make it a file.
I'd argue that the API that requires a
ifstream&
instead ofistream&
is probably wrong, because there's rarely a reason to assume such things about youristream&
-ifstream
,istringstream
etc can all be passed just fine.
As long as the API is like that, you will need a file:
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <fstream>
namespace io = boost::iostreams;
int main(int argc, char** argv) {
assert(argc>1);
// Read from the first command line argument, assume it's gzipped
std::ifstream file(argv[1], std::ios::binary);
io::filtering_istreambuf inbuf;
inbuf.push(io::gzip_decompressor());
inbuf.push(file);
// Convert streambuf to istream
{
std::ofstream ofs("temp.dat", std::ios::binary);
io::copy(inbuf, ofs);
}
std::ifstream instream("temp.dat");
}
For the test run
g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp -lboost_iostreams
gzip -k main.cpp
./a.out main.cpp.gz
md5sum temp.dat main.cpp
Prints
6e2d99a75e7f637e9c07e9c78acb04f4 temp.dat
6e2d99a75e7f637e9c07e9c78acb04f4 main.cpp
Upvotes: 1