views:

217

answers:

5

After a lot searching for solutions I've decided to actually ask for some help!

I have a file that consists of a number of blocks, where each block may or may not be compressed. Before each block is an indication of the size of the block and whether the block is compressed. Within each block is a string that identifies the block. Given a block name I would like to get the associated block from the file.

My first thought is to read the compression flag and the size of the block, read just the block into an istringstream, decompress the istringstream if needed, then search for the block name. I can read the compression flag and the size of the block, but I'm at a loss as to how to read the block of file data into the istringstream. I see where people have read entire files into a istringstream but I don't want to do that because each block may or may not need to be decompressed.

Any ideas or a link to a solution that I missed? Or is there a better algorithm? Thanks for any comments.

A: 

Untested, but something like this ought to work:

// open file, and seek to the appropriate position
// read 'length', the size of your chunk in bytes
std::vector<char> buffer(length);
file.read(&buffer[0],length);
file.close();
// decompress or manipulate the buffer as needed
std::istringstream iss;
iss.rdbuf()->pubsetbuf(&buffer[0],length); // here's the magic
luke
+2  A: 

Why you need to read the data into a memory stream; why not just read it into an array or an std::vector?

Pavel Minaev
If you're decompression routine is using C-style strings and you know the buffer size up front, you should definitely just be reading into an array of char.
mrkj
A: 

I prefer a stream because of my decompression routine, which uses C-style strings.

But, I should be able to cast a std::vector into what's needed by the compression/decompression routines so once I get the reading part working I'll look into it.

A separate component to all this is pulling the useful data from the block. I haven't actually looked too closely into reading from the istringstream so depending on how that goes will probably dictate my desire to process from a std::vector of process from an istringstream.

Thanks to both of you. Looks like I have to interpret what Bjarne says about pubsetbuf :).

George S. Hugh
piotr
A: 

Use iterators.

my_fstream >> compressed_size;
stringstream compressed_data;
istream_iterator<char> file_fetch_iter( my_fstream );
ostream_iterator<char> buffer_put_iter( compressed_data );

for ( size_t i = 0; i < compressed_size; ++ i ) {
    * buffer_put_iter ++ = * file_fetch_iter ++;
}

legacy_decompressor( compressed_data );
Potatoswatter
A: 

Streams, as the name implies are intended for streamed text or binary processing. You are interested in reading blocks, so getting data into an string stream does't make much sense to me.

An elegant approach would be to implement your own stream, using std::streambuf etc. as base. And then you will read and buffer blocks at the input, handling compression or not, and have a stream of data at the output, where you can properly read data with the usual operators into strings, integers etc.

Otherwise you are stuck using the stream read method much like a system call to read data into a buffer. In this case I'd suggest reading data into a vector and not slowing things anymore by using an additional stringstream.

You can find examples for implementing your own stream class around the net, such as gzstream. The book Standard C++ Iostreams and Locales book is useful too.

piotr