Ignoring for a moment the age old argument of whether people prefer the old C-Style file access functions, or should always use the newer c++ classes, the fact of the matter is that you will eventually run into code using C-Style functions, and you should know what it is doing.
Just for fun, let us use the actual c compiler (gcc) instead of g++. Compile the source code with the following commands:
gcc -c -o mycopy_cpp.o mycopy_cpp.cpp gcc -o mycopy_cpp mycopy_cpp.o
The way to run this file (as it should tell you if you run it without arguments) is to give it first the source file to copy from, then the filename to copy to.
Assuming you have a file "test.txt" (and you have permission to write to a new file in this directory) you should see output like the following:
$ ./mycopy_c test.txt newfile.txt Copying test.txt to newfile.txt. $
#include <stdio.h>
"stdio.h" includes all the functions that we will need to write this program, namely: "printf", "fopen", "fread", "fwrite", and "fclose".
#define BUFSIZE (1024)
We will need a memory buffer to hold data as we are transferring it between the files. This preprocessor definition will hold the size of this buffer for use later in our code.
Now let us skip down to the actual work-horse function: mycopy_cpp
int mycopy_c( const char *sSrc, const char *sDest )
We will take two character strings, the first representing the source filename, and the second, the destination. We will return an exit code.
char buf[BUFSIZE];
This is our memory buffer. Note the size of it is defined by "BUFSIZE".
FILE *fhIn, *fhOut; size_t iSize;
When we open a file, the type it returns is a "FILE *", typically referred to as a file handle. We will need one for our source file (fhIn) and one for the destination file (fhOut). the "fread" and "fwrite" functions return the number of bytes they dealt with in the data type of "size_t".
fhIn = fopen( sSrc, "rb" ); if( !fhIn ) { printf( "mycopy_c: Error reading from \"%s\".\n", sSrc ); return 2; }
"fopen" takes a character string representing the filename to open, and a string indicating the mode in which to open the file. "r" indicates read, "w" for write, and "a" for append. "b" stands for binary, and helps ensure consistency when compiling on non-posix systems.
If "fopen" returns 0 (NULL), then we were not successful in opening the file, we should report to the user and exit with an error code.
fhOut = fopen( sDest, "wb" ); if( !fhOut ) { printf( "mycopy_c: Error writing to \"%s\".\n", sDest ); fclose( fhIn ); return 3; }
If there is an error opening the destination file, we have the additional requirement of cleaning up the source (fhIn) filehandle that *was* opened successfully.
iSize = fread( buf, sizeof( buf[0] ), BUFSIZE, fhIn ); while( iSize > 0 ) { fwrite( buf, sizeof( buf[0] ), iSize, fhOut ); iSize = fread( buf, sizeof( buf[0] ), BUFSIZE, fhIn ); }
The "fread" and "fwrite" functions have a possibly unexpected "size" parameter for the purposes of reading and writing discreet chunks of data (i.e. raw struct data). As we are dealing with raw data, we set this to the size of a single character in our memory buffer "sizeof( buf[0] )".
So we pass these functions our memory buffer (buf), the size of one "element", the number of "elements" up to which the function will read/write (BUFSIZE), and the file handle to read or write from/to.
"fread" returns the number of elements actually read into "iSize". We loop until fread returns zero, immediately writing the data in our buffer to fhOut.
fclose( fhIn ); fclose( fhOut );
"fclose" will clean up our file handles.
You should now be able to read and write binary file data utilizing the C-Style file access functions.