I want to create a file qbc.txt. I know how to create it, but I want to create a program that, if a file already exists with the same name, it would rename it to qbc(1).txt.
-
1Try to open the file with said name in read mode (e.g. with `ifstream`) first. If it can be opened, then the file already exists and you need to try the next name. If it can't be opened, then it probably doesn't exist, and you open it again in write mode. – HolyBlackCat Feb 02 '18 at 17:37
-
If i open and file already exist then how it would create new file with same name with (1) added like it is created in windows if we download two things it saves with name download and download (1) like this – Athar Qazi Feb 02 '18 at 17:41
-
I don't understand the question. Do you ask how to add `(1)` to the file name? – HolyBlackCat Feb 02 '18 at 17:43
-
Yes. I want to ask that if the file already exist then my program should save it with addind (1) to it – Athar Qazi Feb 02 '18 at 17:45
-
`filename = filename + "(1)";` where `filename` is a `std::string` you used to try to open it with. – Galik Feb 02 '18 at 17:45
-
Thnks man!! Solved my 90% of issue – Athar Qazi Feb 02 '18 at 17:54
-
Not a duplicate. The other question only talks about detection of the existing file. It does not explain how to avoid the inherent race condition in trying to rename a possible existing file before creating a new one with the same name. – Adrian McCarthy Feb 02 '18 at 18:42
4 Answers
In C++17, boost's filesystem library was standardized as std::filesystem
It comes with a convenient std::filesystem::exists function.
It accepts a std::filesystem::path object, but fortunately those can be constructed with a std::string
, making our program trivially easy:
std::string prefix = "qbc";
std::string extension = ".txt";
std::filesystem::path filename{prefix + extension};
int i = 0;
while (std::filesystem::exists(filename)){
filename = prefix + "(" + std::to_string(++i) + ")" + extension;
}
// now filename is "qbc(1)" or "qbc(2)" etc.
Unfortunately no compiler has full support for it at the time of this writing!

- 39,700
- 8
- 109
- 143
-
Like the other answers, `std::filesystem` suffers from the same race condition problems. If another process creates a file with that name after you've checked for existence and before you create your own, then it doesn't do what you want. (Imagine running multiple copies of the program at once.) – Adrian McCarthy Feb 02 '18 at 19:17
-
@AdrianMcCarthy: Thank you for pointing that out. The filesystem is indeed a shared resource. Can that same comment not be levied against most answers on this site? – AndyG Feb 02 '18 at 19:19
-
what do you mean with "was standarized as std::filesystem"? I always though Cpp standards are just "interfaces" and not implementations, so it could not be a Boost implementation, am I wrong? – Melardev May 15 '19 at 15:01
-
@Melardev: The boost implementation was standardized (with a few changes). Refer to [`[filesystems]`](http://eel.is/c++draft/filesystems). The C++ standard is a specification for implementors. The specification says that they must provide an abstraction over the filesystem. – AndyG May 15 '19 at 15:13
-
@AndyG Ok, so what you meant was that the specification was designed in such a way boost was(or almost was) already compliant with.But obviously the implementation is up to the compiler developers. – Melardev May 15 '19 at 15:22
Here is a simple solution. The file_exists()
function came from @Raviprakash in his response. I've added how to change the filename and try again until success. I've done an approach similar to this before in Python.
If you know that your program is the only one that will create or remove these files, then you can cache the last created one and simply create the next one instead of looping over all of the created ones every time. But this kind of optimization would only make sense if you plan to make hundreds of thousands of files this way.
#include <fstream>
#include <string>
bool file_exists(const std::string &filename) {
std::ifstream in(filename);
return in.good();
}
std::ofstream& open_new(std::ofstream &out, std::string prefix,
std::string suffix)
{
std::string filename = prefix + suffix;
unsigned int index = 0;
while (file_exists(filename)) {
index++;
filename = prefix + "(" + std::to_string(index) + ")" + suffix;
}
out.rdbuf()->open(filename, std::ios_base::out);
return out;
}
int main() {
std::string prefix = "qbc";
std::string suffix = ".txt";
std::ofstream out;
open_new(out, prefix, suffix);
out << "hello world!\n";
return 0;
}

- 311
- 1
- 5
I know the program needs some improvements but the general idea is here:
#include <fstream>
#include <string>
using namespace std;
inline bool file_exists(const std::string& name)
{
ifstream f(name.c_str());
return f.good();
}
int main()
{
string filename, name;
name = "qbc";
filename = name;
int counter = 1;
while (file_exists(filename+".txt")) {
string str = to_string(counter);
filename = name+ "(" + str + ")";
counter++;
}
filename += ".txt";
ofstream out(filename.c_str());
return 0;
}

- 1,110
- 2
- 16
- 34
-
There's a race condition here. You may decide to create a file called `xyz(3).txt` because that one doesn't exist yet, but another process might create a file with that name before you actually do. This is a tricky problem to solve, especially when you restrict yourself to C++ standard library (and it's an inherent problem in forthcoming filesystem handling library proposed for the next standard). – Adrian McCarthy Feb 02 '18 at 18:46
I don't think this can be entirely solved using just the standard libraries. You can certainly keep picking a new file name until you find one that's unused and then create the new file (as the other answers have shown).
But there's an inherent race condition in that approach. What if another process creates a file between the time your program decides the name is available and the time it actually creates the file? Imagine two copies of your program both trying to write out files.
What you need is an atomic way to check for the file's existence and also to create the file. The normal way to do that is to first just try to create the file and then see if you succeeded or not. Unfortunately, I don't think the standard C++ or C libraries give you enough tools to do that. (I'd be happy to be proven wrong about that.)
Operating systems often provide APIs for doing just that. For example, Windows has GetTempFileName, which just keeps trying to create a new file until it succeeds. The key is that, once it succeeds, it keeps the file open so that it knows no other process can steal the name that's been selected.
If you tell us which OS you're using, we might be able to provide a more detailed answer.

- 45,555
- 16
- 123
- 175