Romz
Romz

Reputation: 1457

The best way to save data from std::istream to file

I have some data in std::istream and I need to save it to the disk. Here is my draft:

    std::istream& i_stream = ReceiveBytes();

    FILE* pFile;
    pFile = fopen("C:\\my_file.exe", "wb");
    char buffer[1024] = {0x0};
    i_stream.read(buffer, 1024);
    std::streamsize n = i_stream.gcount();

    while (n > 0)
    {  
        if (i_stream)
        {
            fwrite(buffer, sizeof(char), sizeof(buffer), pFile);
            i_stream.read(buffer, 1024);
            n = i_stream.gcount();
        }
        else n = 0;
    }

    fclose(pFile);

For some reason I don't save all the data from i_stream, I lose about 50 bytes in the end of the i_stream. What did I do wrong in the code? Is there any better solutions to save data from std::istream to a file ?

Upvotes: 3

Views: 4914

Answers (2)

Rob11311
Rob11311

Reputation: 1416

CRLF ("\r\n") input sequences, might be converted to simple LF ("\n"). There's a bug in the fwrite, the code attempts to write 1024 bytes, no matter what. There's no error checking on the output open, write or close.

More idiomatic is to have the input tests once in the while condition :

std::streamsize n;
i_stream.read(buffer, 1024);
while (i_stream || (n = istream.gcount()) != 0) {
    fwrite(buffer, sizeof(char), n, pFile);
    if (n) { i_stream.read(buffer, 1024) };
}

By mixing C++ streams and C stdio functions, the code's less consistent, than if it used streams for both read and write. An example of code to copy a binary file, using ifstream & ofstream is given at http://www.cplusplus.com/reference/ostream/ostream/write/ which might be helpful.

Upvotes: 4

James Kanze
James Kanze

Reputation: 153929

There are two possible issues. The first is that the std::istream you're using may not have been opened in binary mode; you don't show us this. The second is that you're using unformatted input. If you don't read the full 1024 bytes, then the failbit will be set in i_stream. The test for having read anything (even less than enough) bytes with a formatted read is i_stream || istream.gcount() != 0 (or for failure, !istream && istream.gcount() == 0).

Upvotes: 2

Related Questions