tags:

views:

94

answers:

4

This is the code I have, but the file is a little smaller and doesn't execute:

int WriteFileContentsToNewFile(string inFilename, string outFilename)
{
    ifstream infile(inFilename.c_str(), ios::binary);
    ofstream outfile(outFilename.c_str(), ios::binary);

    string line;
    // Initial read
    infile >> line;
    outfile << line;
    // Read the rest
    while( infile )
    { 
        infile >> line;
        outfile << line;
    }

    infile.close();
    outfile.close();

    return 0;
}

What am I doing wrong? Is there a better way to read in the binary of an executable file and immediately write it out to another name? Any code examples?

I need to do it without a system copy in order to simulate writing to disk.

+2  A: 

The stream operator>>() performs formatted input even if you open the stream in binary mode. Formatted input expects to see strings of printable characters separated by spaces, but this is not what binary files like executables consist of. You need to read the file with the stream's read() function, and write it with the output stream's write() function.

anon
+4  A: 

One way is to use the stream inserter for a streambuf:

int WriteFileContentsToNewFile(string inFilename, string outFilename)
{
    ifstream infile(inFilename.c_str(), ios::binary);
    ofstream outfile(outFilename.c_str(), ios::binary);

    outfile << infile.rdbuf();
}
Jerry Coffin
+1 with a nit: I *think* that, to be extra sure that there is no interference from the codecvt facet, `std::locale::classic()` should be `imbue()`-ed on the streams too.
Éric Malenfant
This is an interesting concept. I'll try this one out a little later b/c there are less lines of code than the one I ended up going with. Can anyone verify that this does the job?
Brian T Hannan
@Éric Malenfant:Yes, if the rest of the code were changing the global locale, that would probably be a good thing to do.
Jerry Coffin
I will only be using English, so it's probably of no concern to me.
Brian T Hannan
It does work, but the run time is 3 seconds slower than the example I found (http://www.cplusplus.com/reference/iostream/ostream/write/) on a faster machine (4 GBs RAM, Intel [quad] Core i7, 2.67 GHz, 64-bit Win7 Ultimate). Any reason for the major slowdown?
Brian T Hannan
There are too many possibilities to even guess at reasons for differences in speed, and most of what you've specified is irrelevant (e.g., hard drive speed will usually matter more than CPU speed).
Jerry Coffin
This solution actually works better than the example in the link I provided. There were problems allocating memory space or something in certain situations. This one works under all conditions I have noticed so far.
Brian T Hannan
I suspect your two comments are related: it (probably) uses a smaller buffer, which makes it a bit slower, but also more dependable when you're short on memory.
Jerry Coffin
A: 

Off the top of my head: (no error checking)

EDIT: Changed to fix feof bug.

int WriteFileContentsToNewFile(string inFilename, string outFilename)
{
  FILE* in = fopen(inFilename.c_str(),"rb");
  FILE* out = fopen(outFilename.c_str(),"wb");
  char buf[4096]; //1024 is a habit of mine. 4096 is most likely your blocksize. it could also be 2<<13 instead.
  int len;
  while( (len = fread(buf,1,1024,in)) > 0 )
  {
    fwrite(buf,1,len,out);
  }
  fclose(in);
  fclose(out);
}
KitsuneYMG
What if you have greater than 1024 bytes in the file? The example I used checks the length of the file it reads in.
Brian T Hannan
This has an obvious bug. Never use `feof(stream)` as the condition for a loop. It's possible to make it work correctly, but not easy, and requires at least one other exit from the loop to work correctly. The same goes for the equivalent using iostreams.
Jerry Coffin
@Brian T Hannan:a longer file won't cause a problem -- it attempts to repeat the loop 'til it reaches the end of the file. Working in 1K chunks may be somewhat slow, but code like this can be made to work correctly.
Jerry Coffin
It's also a good idea to check that files did actually open. Oh, and those filename function parameters should be const references.
anon
Good call with the const. I changed it.
Brian T Hannan
In production code I would check in and out to make sure they aren't null. I'd also check errno and ferror in the loop. I didn't because error handling code tends to clutter up examples.
KitsuneYMG
A: 

(unix) the system cp command not only copies the contents of the file, but also copies (some) of the file permissions, which include the execute bit.

Make sure your copy also sets the execute bit on the output file as appropriate.

Alex Brown