Copy Files in C++

I'm wondering if there's a way to copy files in C++ using string variables. ALSO, the file paths/names may have spaces.

For example, let's say this C++ app is going through a list of recently modified files:
C:\Folder1\file1.ext
D:\Folder Number 2\File Number 2.ext
E:\Folder #3\File #3.ext
etc.

And I want to copy them as such:
F:\Copied Files\File 1.ext
F:\Copied Files\File 2.ext
F:\Copied Files\File 3.ext
etc.

I have made the appropriate string function to format the output as necessary, but I need to find a C++ function to copy file longer than standard DOS 8.3 filename format. Is there any such beast, or am I in need of a VisualC++ class?
RunBorisAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Kent OlsenData Warehouse Architect / DBACommented:
Hi Boris,

It seems that you have already determined what files to copy so the hard part is done.

To copy the files, it's probably easiest to call the system's copy utility.

char Command[1000];

  strcpy (Command, "copy ");   //  For DOS / Windows
  strcpy (Command, "cp ");      //  For unix / linux

  strcat (Command, sourcfilename);
  strcat (Command, " ");
  strcat (Command, "newfilename);

  system (Command);


That should do the trick,

Kent
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
RunBorisAuthor Commented:
That didn't quite work. Part of the problem is most of the copy function I've seen require a CONST CHAR input. I need it to accept string variables. The strings I have are strSource & strDestination. These strings can be quite extensive. For example, one strSource in the listArray may be "C:\My Documents\My Music\Panic! At The Disco\(2005) A Fever You Can't Sweat Out\02 - The Only Difference Between Martyrdom And Suicide Is Press Coverage.mp3", and the corresponding strDestination might be "D:\Backup Files\Music\Panic! At The Disco - The Only Difference Between Martyrdom And Suicide Is Press Coverage.mp3". And this process would repeat for every item in the listArray, possibly hundreds of times. Anywho, here's the errors I got:

345 \main.cpp no matching function for call to `strcat(char[1000], std::string&)'
note C:\Dev-Cpp\include\string.h:41 candidates are: char* strcat(char*, const char*)
0
SeanDurkinCommented:
use std::string's c_str() function to get the const char * version of the string:

strSource.c_str();
0
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

Kent OlsenData Warehouse Architect / DBACommented:

Hi Boris,

system () wants a char*, not an std::string.

To go forward with this approach, you can build the command up in a char* buffer and pass it, or build the command up as a std::string and pass the address of the string's buffer.

Either way you'll call the c_str() method, as Sean indicates.  The only issue when the method gets called.

It's probably a bit cleaner to do the latter.  Build an std::string object.  That pretty much eliminates buffer overruns or other similar problems.

  std::string Command;

  Command = "copy ";   // Command = "cp " for a *nix system
  Command = Command + strSource;
  Command = Command + " ";
  Command = Command + strDestination;

  system (Command.c_str ());

Note that the entire generated string can not be longer than the longest legal command line.


Kent
0
Kent OlsenData Warehouse Architect / DBACommented:

And of course,

char Command[1000];

snprintf (Command, 1000, "copy %s %s", strSource.c_str (), strDestination.c_str ());

system (Command);


0
RunBorisAuthor Commented:
ok, that actually did work. HOWEVER, for long filenames and spaces, I had to add quotation marks to the beginning and end of the strings. Thanks!
0
evilrixSenior Software Engineer (Avast)Commented:
Using the system() function to copy files means you don't have good control over error handling. What do you do if the file already exists or if the file can't be copied for some reason? There are many things that could go wrong and trying to figure out what and how to deal with it just from the error status code returned by system isn't likely to be very easy. Below I've written you a small function that will copy a file programmatically. It has the option to force overwrite if the file already exists.

I've tested this code using my own test sample and it worked file; however, if you do decide to use this code you should test it thoroughly before putting it into a production environment.

I hope this helps.

-Rx.
#include <io.h>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>
 
 
void copy_file(std::string const & sOldPath, std::string const & sNewPath, bool bOverWrite = false)
{
	if(!bOverWrite && (0 == access(sNewPath.c_str(), 0x00))) { throw std::runtime_error("Output file already exists"); }
 
	std::ifstream ifs(sOldPath.c_str(), std::ios::binary);
	if(!ifs.is_open()) { throw std::runtime_error("Unable to open input file"); }
 
	std::ofstream ofs(sNewPath.c_str(), std::ios::trunc | std::ios::binary);
	if(!ofs.is_open()) { throw std::runtime_error("Unable to open output file"); }
 
	ifs.seekg(0, std::ios::end);
	std::ifstream::pos_type size = ifs.tellg();
	ifs.seekg(0);
 
	std::string sData(size, std::string::value_type());
 
	ifs.read(&sData[0], size);
	if(!ifs.good()) { throw std::runtime_error("Unable to read input file"); }
 
	ofs.write(sData.data(), size);
	if(!ifs.good()) { throw std::runtime_error("Unable to write output file"); }
}
 
int main()
{
	int nRetval = 0;
 
	try
	{
		std::string sOldPath = "c:\\temp\\test.txt";
		std::string sNewPath = "c:\\temp\\newtest.txt";
 
		copy_file(sOldPath, sNewPath);
 
		std::cout << "Copied " << sOldPath << " to " << sNewPath << " successfully." << std::endl;
	}
	catch(std::exception const & ex)
	{
		std::cerr <<"Error. " << ex.what() << std::endl;
		nRetval = -1;
	}
 
#ifdef WIN32
	system("pause"); // Only works on Windows
#endif
 
	return nRetval;
}

Open in new window

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.