When working with files, one of the actions a program may often need to do is make a second copy of a file, rename a file, or remove a file which is not going to be needed later. The free functions std::filesystem::copy_file, std::filesystem::rename, and std::filesystem::remove perform these three tasks, respectively.
To make a second copy of an already existing file, use std::filesystem::copy_file. It takes two path objects as arguments: the source and the destination pathnames.
#include <iostream>
#include <filesystem>
#include <fstream>
int main()
{
{
std::ofstream out{"original.txt"};
out << "hello\n";
}
std::filesystem::path from{"original.txt"};
std::filesystem::path to{"copy.txt"};
// Check this condition before entering the block
if (std::filesystem::copy_file(from, to))
std::cout << "copied\n";
else
std::cout << "not copied\n";
return 0;
}
The first block creates the file original.txt containing some string, then creates the two path object values, from is source; to is destination, and attempts to create a new file called to which is a copy of the file called from. If this is successful, a message is printed, and otherwise an alternative message is displayed; true indicates success, and false, failure. Even though they hold the same characters, after a successful copy the two files are distinct entries in the file system; even though they now hold the same characters, the to path could now be renamed or removed with no effect to from, and vice versa.
The destination will be replaced if it already exists when the overwrite_existing constant is added as a third argument.
#include <iostream>
#include <filesystem>
#include <fstream>
int main()
{
{
std::ofstream out{"original.txt"};
out << "hello\n";
}
{
std::ofstream out{"copy.txt"};
out << "old\n";
}
std::filesystem::path from{"original.txt"};
std::filesystem::path to{"copy.txt"};
// Copy this filesystem entry
if (std::filesystem::copy_file(
from,
to,
std::filesystem::copy_options::overwrite_existing))
{
std::cout << "copied\n";
}
else
{
std::cout << "not copied\n";
}
return 0;
}
Both the source and the destination files are created, with different content, prior to the function call to std::filesystem::copy_file, with an additional argument which indicates the source should be copied and the destination should be replaced if an object with that path name exists. A message is printed indicating success, and "copied" is displayed. Without the constant in the call, the call would have failed and the original destination object would not have been changed.
When an object is already present in the file system, and a reference to it should be changed to a reference to some other source object, call std::filesystem::rename.
#include <iostream>
#include <filesystem>
#include <fstream>
int main()
{
{
std::ofstream out{"oldname.txt"};
out << "data\n";
}
std::filesystem::path from{"oldname.txt"};
std::filesystem::path to{"newname.txt"};
// Rename or move this filesystem entry
std::filesystem::rename(from, to);
if (std::filesystem::exists(to))
std::cout << "renamed\n";
else
std::cout << "not renamed\n";
return 0;
}
The block then creates a file called oldname.txt, creates two path like objects, from points to the current file, and to points to where it should be renamed. The call std::filesystem::rename(from, to) renames the source to the destination. When this operation is successful, the test to std::filesystem::exists(from) will be false, and the test to std::filesystem::exists(to) will be true, and "renamed" will be printed.
Any operation where the destination file already exists or the source file does not exist would cause an exception of type std::filesystem::filesystem_error to be thrown.
A second file with the destination name is not created prior to the function call, but if one were, it would be replaced.
When an object is not going to be needed anymore, call std::filesystem::remove.
#include <iostream>
#include <filesystem>
#include <fstream>
int main()
{
{
std::ofstream out{"temp.txt"};
out << "temporary\n";
}
std::filesystem::path p{"temp.txt"};
// Remove this filesystem entry
if (std::filesystem::remove(p))
std::cout << "removed\n";
else
std::cout << "not removed\n";
return 0;
}
The block then creates temp.txt, and provides it to the path object p. The call std::filesystem::remove(p) deletes the referenced file. Whether the deletion succeeds, a true or false value is returned, along with a message either indicating "removed" or that the file could not be found or deleted. After the call to remove, the path p no longer refers to an object in the file system.
These three operations can be conveniently strung together into a typical file lifetime workflow: create a file, make an archive copy, then rename the archive to a better name and discard the original working copy.
#include <iostream>
#include <filesystem>
#include <fstream>
int main()
{
{
std::ofstream out{"scratch.txt"};
out << "work in progress\n";
}
std::filesystem::path scratch{"scratch.txt"};
std::filesystem::path backup{"scratch.bak"};
std::filesystem::path final{"result.txt"};
std::filesystem::copy_file(scratch, backup);
std::filesystem::rename(backup, final);
std::filesystem::remove(scratch);
// Check whether this filesystem path exists
if (std::filesystem::exists(final) &&
!std::filesystem::exists(scratch))
{
std::cout << "done\n";
}
else
{
std::cout << "failed\n";
}
return 0;
}
The file scratch.txt is created first. It is then copied to scratch.bak, where it becomes an archive copy. The scratch.bak file is then renamed to result.txt, and the original working file scratch.txt is deleted. The final check ensures that the persistent file exists and that the temporary file does not, and prints "done".
0 comments
No comments yet. Be the first.