Search code examples
c++file-iostringstreamcarriage-returnfile-copying

Error when copying a binary file with ifsream and stringstream


I'm attempting to strip the header from an image file which contains a plain text header followed by binary image information. As a precursor to this I would like to copy the files information into a stringstream for editing. When doing this I encountered some issues which led me to try simply reading in the file and writing it back out again as a new file for debugging purposes. When I did this the new file ended up being about 1kb larger than the original. When doing a binary compare in UltraEdit it seems that anywhere the HEX character 0A (Line Feed I believe) appears my program seems to have added in 0D(carriage return) right before it. I was wondering what the cause of this behaviour was and how to avoid it if possible. Code snippet follows:

....
std::string inputFilename = argv[1];
std::ifstream in( argv[1],ios::out | ios::binary);
if ( in )
{
std::stringstream fileStream;
fileStream<<in.rdbuf();
cout<<fileStream.str().length(); //debugging
in.close();
ofstream myfile;
myfile.open("selfoutput");
myfile<<fileStream.str();
myfile.close();
....

Thanks for any help! -David


Solution

  • Try ios:in

    std::ifstream in( argv[1],ios::in | ios::binary)
    

    Or, in fact

    std::ifstream in( argv[1],ios::binary)
    

    Which is equivalent:

    First, performs the same steps as the default constructor, then asssociates the stream with a file by calling rdbuf()->open(filename, mode | std::ios_base::in).. If the open() call returns a null pointer, sets setstate(failbit)

    Here's my (untested) simplist take on it:

    #include <fstream>
    
    int main(int /*argc*/, const char *argv[])
    {
        std::ifstream in(argv[1], std::ios::binary);
        if (in)
        {
            std::ofstream myfile("selfoutput", std::ios::binary);
            if (myfile)
                myfile << in.rdbuf();
        }
    }
    

    In the interest of gratuitous code golf and bad style:

    #include <fstream>
    using namespace std;
    
    int main(int /*argc*/, const char *argv[]) {
        ofstream("selfoutput", ios::binary) << ifstream(argv[1], ios::binary).rdbuf();
    }