Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading chunks from a file in binary mode to a buffer and writing that buffer to another file

I am trying to achieve something like this:

while (ifstream has not been entirely read)
{
   read a chunk of data into a buffer that has size BUFLEN
   write this buffer to ostream
}

At first I tried to achieve this by using ifstream.eof() as my while condition, but I've heard that this is not the way to go. I've been looking at std::ios::ifstream's other functions, but can't figure out what else to use.

PS: I am using a buffer because the file that is being transferred can get very big.

like image 743
codd Avatar asked Nov 25 '11 13:11

codd


2 Answers

The iostream classes take care of all necessary buffering, so you don't have to. The usual idiom to copy an entire file is just:

fout << fin.rdbuf();

iostream takes care of all of the necessary buffering. (This is a somewhat unusual use of <<, since it doesn't format. Historical reasons, no doubt.)

If you need the loop, perhaps because you want to do some transformations on the data before rewriting it, then it's a little tricker, since istream::read “fails” unless it reads the requested number of characters. Because of this, you have to also check how many characters were read, and process them even if the read failed:

int readCount;
while ( fin.read( &buf[0], buf.size() )
        || (readCount = fin.gcount()) != 0 ) {
    //  ...
    fout.write( &buf[0], readCount );
}

This is fairly ugly; a better solution might be to wrap the buffer in a class, and define an operator<< for this class.

like image 154
James Kanze Avatar answered Nov 19 '22 23:11

James Kanze


The istream::read function returns the stream, which can be used as a boolean expression, so you can do something like:

while (is.read(buffer, BUFLEN))
{
    outputfile.write(buffer, is.gcount());
}

if (is.eof())
{
    if (is.gcount() > 0)
    {
        // Still a few bytes left to write
        outputfile.write(buffer, is.gcount());
    }
}
else if (is.bad())
{
    // Error reading
}

You might want to check that the write inside the loop doesn't fail too.

like image 35
Some programmer dude Avatar answered Nov 19 '22 22:11

Some programmer dude