Qt: Как найти ближайшего существующего предка пути, который сам может существовать или не существовать
Мотивирующий пример:
В предыдущем сеансе приложение сохраняло некоторый путь, выбранный пользователем. Тем временем этот путь мог быть удален, перемещен, переименован или диск отключен. Приложение теперь хочет позволить пользователю искать путь через
QFileDialog
и для удобства пользователя предыдущий путь передается в качестве начального каталога файлового диалога, поскольку предположительно новый путь, вероятно, будет находиться рядом со старым путем. К сожалению, еслиQFileDialog
дается начальный путь, который не существует, по умолчанию используется текущий рабочий каталог, что вряд ли будет полезным для пользователя, поскольку обычно это каталог установки приложения.Таким образом, мы хотели бы предварительно обработать старый путь, чтобы он указывал на каталог, который действительно существует, прежде чем передать его
QFileDialog
, Если старый путь не существует, мы хотели бы заменить его на ближайший каталог, который существует.
Так как же взять путь к файлу (который может существовать или не существовать) и искать "вверх" по этому пути, пока не найдет что-то, что действительно существует в файловой системе?
2 ответа
Это два подхода, которые я придумала до сих пор, но предложения по улучшению очень приветствуются.
Поиск вверх, пока не существует путь:
QString GetNearestExistingAncestorOfPath(const QString & path)
{
if(QFileInfo::exists(path)) return path;
QDir dir(path);
if(!dir.makeAbsolute()) return {};
do
{
dir.setPath(QDir::cleanPath(dir.filePath(QStringLiteral(".."))));
}
while(!dir.exists() && !dir.isRoot());
return dir.exists() ? dir.path() : QString{};
}
Поиск вниз, пока путь не существует:
QString GetNearestExistingAncestorOfPath(const QString & path)
{
if(QFileInfo::exists(path)) return path;
auto segments = QDir::cleanPath(path).split('/');
QDir dir(segments.takeFirst() + '/');
if(!dir.exists()) return {};
for(const auto & segment : qAsConst(segments))
{
if(!dir.cd(segment)) break;
}
return dir.path();
}
Попробуйте следующий код:
QString getNearestExistingPath(const QString &path)
{
QString existingPath(path);
while (!QFileInfo::exists(existingPath)) {
const QString previousPath(existingPath);
existingPath = QFileInfo(existingPath).dir().absolutePath();
if (existingPath == previousPath) {
return QString();
}
}
return existingPath;
}
Эта функция использует QFileInfo::dir()
метод, который возвращает родительский каталог для указанного пути. Код зацикливается до тех пор, пока не будет найден существующий путь или пока пути в двух последних итерациях не будут идентичны (это помогает нам избежать бесконечного цикла).
От QFileInfo::dir()
документы:
Возвращает путь родительского каталога объекта в виде
QDir
объект.
Примечание:QDir
возвращаемое значение всегда соответствует родительскому каталогу объекта, даже если QFileInfo представляет каталог.
Я все еще рекомендую вам выполнить некоторые тесты, потому что я могу что-то упустить.