My goal is to determine a filename that is not already taken in a particular folder, in order to save it without erasing any file.
For example, if myname.txt
exists, we should add incremental number like -0000 so it becomes myname-0000.txt
. If both myname.txt
and myname-0000.txt
exist, the filename determined should be myname-0001.txt
and so on.
Also, we want to write the code in a C++/Qt.
EDIT : because some comments state some simplier solution, a preference would be to adopt a certain format for filenames for user convenience : we don't want myname-10.txt
determined after myname-9.txt
because Windows file explorer shows myname-10.txt
before myname-9.txt
when ordered by name
My solution is this code (please tell me if you think to a better code) :
// returns the path that will not erase any existing file, with added number in filename if necessary
// argument : the initial path the user would like to save the file
QString incrementFilenameIfExists(const QString &path)
{
QFileInfo finfo(path);
if(!finfo.exists())
return path;
auto filename = finfo.fileName();
auto ext = finfo.suffix();
auto name = filename.chopped(ext.size()+1);
auto lastDigits = name.last(4);
if(lastDigits.size() == 4 && lastDigits[0].isDigit() && lastDigits[1].isDigit() && lastDigits[2].isDigit() && lastDigits[3].isDigit() && lastDigits != "9999")
name = name.chopped(4)+(QString::number(lastDigits.toInt()+1).rightJustified(4,'0'));
else
name.append("-0000");
auto newPath = (path.chopped(filename.size()))+name+"."+ext;
return incrementFilenameIfExists(newPath);
}
EDIT : With some recommandations in the comments, I adapted the code to be able to choose the number of digits :
// returns the path that will not erase any existing file, with added number in filename if necessary
// arguments : the initial path the user would like to save the file ; the number of digits (>=1) we would like to use for incremental number
QString incrementFilenameIfExists(const QString &path, unsigned char ndigits)
{
QFileInfo finfo(path);
if(!finfo.exists() || ndigits == 0)
return path;
auto filename = finfo.fileName();
auto ext = finfo.suffix();
auto name = filename.chopped(ext.size()+1);
auto lastDigits = name.last(ndigits);
bool aredigits = true;
for(QChar &c : lastDigits)
{
if(!c.isDigit())
{
aredigits = false;
break;
}
}
QString zeros = "0";
zeros = ("-")+(zeros.rightJustified(ndigits,'0'));
QString nines = "9";
nines = nines.rightJustified(ndigits,'9');
if(lastDigits.size() == ndigits && aredigits && lastDigits != nines)
name = name.chopped(ndigits)+(QString::number(lastDigits.toInt()+1).rightJustified(ndigits,'0'));
else
name.append(zeros);
auto newPath = (path.chopped(filename.size()))+name+"."+ext;
return incrementFilenameIfExists(newPath,ndigits);
}