Qtファイルパス操作の秘訣:QFileInfo::absoluteDir()徹底解説

2025-05-31

QFileInfo::absoluteDir() は、QFileInfo オブジェクトが表すファイルの親ディレクトリの絶対パスを返します。

具体的には、以下の特徴があります。

  1. 戻り値
    QDir 型のオブジェクトを返します。この QDir オブジェクトは、対象のファイルが格納されているディレクトリを表します。
  2. 絶対パス
    返されるパスは、常にルートディレクトリからの絶対パスになります。例えば、C:/Users/YourName/Documents/file.txtabsoluteDir() を呼び出すと、C:/Users/YourName/Documents という QDir オブジェクトが返されます。
  3. シンボリックリンクの解決
    シンボリックリンクを指す QFileInfo オブジェクトに対して absoluteDir() を呼び出す場合、シンボリックリンクが指す実際のファイルの親ディレクトリではなく、シンボリックリンク自体の親ディレクトリが返されます。実際のファイルの親ディレクトリを取得したい場合は、QFileInfo::symLinkTarget() でリンク先のパスを取得し、それを元に新しい QFileInfo オブジェクトを作成して absoluteDir() を呼び出す必要があります。
  4. ファイルが存在しない場合
    QFileInfo オブジェクトが指すファイルが存在しない場合でも、この関数は動作し、そのファイルが存在すると仮定した場合の親ディレクトリの絶対パスを返します。
#include <QCoreApplication>
#include <QFileInfo>
#include <QDebug>
#include <QDir> // QDir を使用するために必要

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 例1: 既存のファイル
    QFileInfo fileInfo1("/home/user/documents/report.txt"); // Linux/macOSの場合
    // QFileInfo fileInfo1("C:/Users/user/Documents/report.txt"); // Windowsの場合
    QDir parentDir1 = fileInfo1.absoluteDir();
    qDebug() << "Path of fileInfo1:" << fileInfo1.absoluteFilePath();
    qDebug() << "Absolute parent directory of fileInfo1:" << parentDir1.absolutePath();
    // 出力例: Absolute parent directory of fileInfo1: "/home/user/documents" または "C:/Users/user/Documents"

    qDebug() << "--------------------";

    // 例2: 存在しないファイル
    QFileInfo fileInfo2("/nonexistent/path/to/some_file.dat");
    QDir parentDir2 = fileInfo2.absoluteDir();
    qDebug() << "Path of fileInfo2:" << fileInfo2.absoluteFilePath();
    qDebug() << "Absolute parent directory of fileInfo2:" << parentDir2.absolutePath();
    // 出力例: Absolute parent directory of fileInfo2: "/nonexistent/path/to"

    qDebug() << "--------------------";

    // 例3: ディレクトリ自身の場合 (QFileInfoがディレクトリを表す場合)
    QFileInfo dirInfo("/home/user/my_project/"); // Linux/macOSの場合
    // QFileInfo dirInfo("C:/Users/user/MyProject/"); // Windowsの場合
    QDir parentDir3 = dirInfo.absoluteDir();
    qDebug() << "Path of dirInfo:" << dirInfo.absoluteFilePath();
    qDebug() << "Absolute parent directory of dirInfo:" << parentDir3.absolutePath();
    // 出力例: Absolute parent directory of dirInfo: "/home/user" または "C:/Users/user"
    // ディレクトリ自身の親ディレクトリが返される点に注意

    return a.exec();
}


ファイル/ディレクトリが存在しない場合の挙動の誤解

問題
QFileInfo::absoluteDir() は、対象のファイルやディレクトリが実際に存在しなくても、パス文字列から親ディレクトリのパスを計算して QDir オブジェクトを返します。この挙動を誤解し、パスが存在することを前提に処理を進めてしまうことがあります。


QFileInfo nonExistentFile("/path/to/nonexistent/file.txt");
QDir dir = nonExistentFile.absoluteDir();
// dir は "/path/to/nonexistent" を指す QDir オブジェクトになりますが、
// このディレクトリ自体が存在するとは限りません。
if (!dir.exists()) {
    qDebug() << "Warning: Parent directory does not exist!";
}

トラブルシューティング
absoluteDir() で取得した QDir オブジェクトが指すディレクトリに対して、ファイル操作(ファイルの作成、リスト取得など)を行う前に、QDir::exists() で実際にディレクトリが存在するかどうかを確認する必要があります。必要であれば、QDir::mkpath() などでディレクトリを作成することも検討してください。

ディレクトリに対する absoluteDir() の挙動の誤解

問題
QFileInfo オブジェクトがディレクトリ自身を表している場合でも、absoluteDir() はその親ディレクトリを返します。ディレクトリ自身を QDir オブジェクトとして取得したい場合に、誤って absoluteDir() を使ってしまうことがあります。


QFileInfo myDirInfo("/home/user/my_project/"); // ディレクトリ "my_project" を指す
QDir parentDir = myDirInfo.absoluteDir();
qDebug() << parentDir.absolutePath(); // "/home/user" が出力される (親ディレクトリ)

// 期待: "/home/user/my_project"
// 実際: "/home/user"

トラブルシューティング
QFileInfo がファイルではなくディレクトリを指している場合に、そのディレクトリ自身を QDir オブジェクトとして取得したい場合は、QFileInfo::absoluteFilePath() を使用してそのディレクトリの絶対パスを取得し、それを元に新しい QDir オブジェクトを作成します。

QFileInfo myDirInfo("/home/user/my_project/");
if (myDirInfo.isDir()) {
    QDir targetDir(myDirInfo.absoluteFilePath());
    qDebug() << targetDir.absolutePath(); // "/home/user/my_project" が出力される
} else {
    // ファイルの場合の処理
    QDir parentDir = myDirInfo.absoluteDir();
    qDebug() << parentDir.absolutePath();
}

または、単に QFileInfo::dir() を使用することもできますが、absoluteDir() の方が常に絶対パスを返すため、より安全です。

相対パスと絶対パスの混同

問題
QFileInfo を相対パスで初期化した場合、absoluteDir() は常に絶対パスを返しますが、その絶対パスの基準はアプリケーションの現在の作業ディレクトリになります。アプリケーションの作業ディレクトリが予期せず変更されたり、開発環境と実行環境で異なる場合に、期待しないパスが返されることがあります。


// アプリケーションの現在の作業ディレクトリが "/home/user/app" であると仮定
QFileInfo relativeFileInfo("data/config.ini");
QDir dir = relativeFileInfo.absoluteDir();
qDebug() << dir.absolutePath(); // "/home/user/app/data" が出力される

// しかし、アプリケーションが別のディレクトリで実行された場合、結果が変わる可能性がある

トラブルシューティング

  • QCoreApplication::applicationDirPath() や QStandardPaths を利用する
    アプリケーションの実行ファイルがあるディレクトリや、OS標準のデータ保存場所など、特定の基準点からのパスを取得したい場合は、QCoreApplication::applicationDirPath()QStandardPaths クラス(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) など)を活用し、そこから相対パスを構築することを検討してください。
  • 常に絶対パスを使用する
    可能な限り、QFileInfo オブジェクトを初期化する際に絶対パスを使用することをお勧めします。これにより、アプリケーションの実行環境に依存しない安定したパスが得られます。

シンボリックリンクの挙動の誤解

問題
QFileInfo がシンボリックリンクを指している場合、absoluteDir()シンボリックリンク自身の親ディレクトリを返します。シンボリックリンクが指す実際のターゲットファイルの親ディレクトリではありません。


/home/user/link_to_file.txt  (-> /data/important/actual_file.txt)

QFileInfo linkInfo("/home/user/link_to_file.txt");
QDir dir = linkInfo.absoluteDir();
qDebug() << dir.absolutePath(); // "/home/user" が出力される

// 期待: "/data/important"
// 実際: "/home/user"

トラブルシューティング
シンボリックリンクが指す実際のファイルの親ディレクトリを取得したい場合は、まず QFileInfo::symLinkTarget() を使用してターゲットのパスを取得し、そのパスで新しい QFileInfo オブジェクトを作成してから absoluteDir() を呼び出します。

QFileInfo linkInfo("/home/user/link_to_file.txt");
if (linkInfo.isSymLink()) {
    QString targetPath = linkInfo.symLinkTarget();
    QFileInfo targetFileInfo(targetPath);
    QDir targetParentDir = targetFileInfo.absoluteDir();
    qDebug() << targetParentDir.absolutePath(); // "/data/important" が出力される
} else {
    QDir parentDir = linkInfo.absoluteDir();
    qDebug() << parentDir.absolutePath();
}

パスセパレータの問題(WindowsとUnix系システム)

問題
Qt は内部的にパスセパレータを自動的に変換してくれるため、ほとんどの場合は問題になりません。しかし、QFileInfo のコンストラクタに渡すパス文字列を手動で構築する際に、Windowsの\(バックスラッシュ)とUnix系の/(スラッシュ)を混在させたり、間違った使い方をすると予期しない結果になることがあります。特に、QString 操作でパスを結合する場合に注意が必要です。


// 意図的に Windows のパスセパレータを使用した場合
QString path = "C:\\Users\\user\\Documents\\file.txt";
QFileInfo fileInfo(path);
QDir dir = fileInfo.absoluteDir();
qDebug() << dir.absolutePath(); // 通常は問題なく C:/Users/user/Documents が返る

// しかし、不適切な結合やエスケープ忘れは問題になる可能性がある
QString dirName = "MyFolder";
QString fileName = "MyFile.txt";
// 悪い例: Windowsで動くがUnix系で動かない可能性
// QString fullPath = "C:\\" + dirName + "\\" + fileName;
// より良い例: QDir::separator() や QDir::filePath() を使う
QString fullPath = QDir("C:/").filePath(dirName).filePath(fileName);
QFileInfo info(fullPath);
qDebug() << info.absoluteDir().absolutePath();
  • フォワードスラッシュ(/)を使用する
    Qt のパス操作においては、内部的にフォワードスラッシュ(/)が推奨されており、Windows環境でも正しく機能します。特別な理由がない限り、パス文字列はフォワードスラッシュで記述すると良いでしょう。
  • Qtのパス操作関数を利用する
    QDir::filePath()QDir::toNativeSeparators()QDir::fromNativeSeparators() など、Qtが提供するパス操作関数を積極的に利用することで、プラットフォーム間の互換性を確保できます。


QFileInfo::absoluteDir() は、ファイルやディレクトリの親ディレクトリの絶対パスを取得するための便利な関数です。ここでは、いくつかの異なるシナリオでの使用例を紹介します。

例 1: 標準的なファイルパスからの親ディレクトリ取得

これは最も一般的な使用方法です。

#include <QCoreApplication>
#include <QFileInfo>
#include <QDebug>
#include <QDir> // QDir クラスを使用するために必要

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 存在するファイルのパスを仮定 (実際には存在しなくても動作します)
    QString filePath = "/home/user/documents/report.txt"; // Linux/macOSの場合
    // QString filePath = "C:/Users/User/Documents/report.txt"; // Windowsの場合

    QFileInfo fileInfo(filePath);

    // absoluteDir() を呼び出して、親ディレクトリの QDir オブジェクトを取得
    QDir parentDir = fileInfo.absoluteDir();

    qDebug() << "元のファイルパス:" << fileInfo.absoluteFilePath();
    qDebug() << "親ディレクトリの絶対パス:" << parentDir.absolutePath();

    // 親ディレクトリ内のファイルやディレクトリをリストアップすることも可能
    qDebug() << "親ディレクトリ内のコンテンツ:";
    for (const QFileInfo &entry : parentDir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot)) {
        qDebug() << "  " << entry.fileName();
    }

    return a.exec();
}

出力例

元のファイルパス: "/home/user/documents/report.txt"
親ディレクトリの絶対パス: "/home/user/documents"
親ディレクトリ内のコンテンツ:
  file1.pdf
  folderA
  report.txt

解説
report.txtQFileInfo オブジェクトを作成し、absoluteDir() を呼び出すことで、その親ディレクトリである /home/user/documents を表す QDir オブジェクトを取得しています。その後、QDir::absolutePath() を使ってその絶対パスを出力し、さらに QDir::entryInfoList() を使って親ディレクトリの内容をリストアップしています。

例 2: 存在しないパスに対する absoluteDir() の挙動

absoluteDir() は、ファイルが存在するかどうかに関わらず、パスから親ディレクトリを導出します。

#include <QCoreApplication>
#include <QFileInfo>
#include <QDebug>
#include <QDir>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 存在しないと思われるパス
    QString nonExistentPath = "/nonexistent/path/to/my_temp_file.tmp";

    QFileInfo fileInfo(nonExistentPath);
    QDir parentDir = fileInfo.absoluteDir();

    qDebug() << "元のパス:" << fileInfo.absoluteFilePath();
    qDebug() << "導出された親ディレクトリ:" << parentDir.absolutePath();

    // 重要: このディレクトリが存在するかどうかを確認
    if (!parentDir.exists()) {
        qDebug() << "注意: この親ディレクトリは現在存在しません。";
        // 必要に応じてディレクトリを作成することも可能
        // if (parentDir.mkpath(".")) { // "." は現在のディレクトリを意味する
        //     qDebug() << "親ディレクトリを作成しました。";
        // }
    }

    return a.exec();
}

出力例

元のパス: "/nonexistent/path/to/my_temp_file.tmp"
導出された親ディレクトリ: "/nonexistent/path/to"
注意: この親ディレクトリは現在存在しません。

解説
nonExistentPath という存在しないパスを与えても、absoluteDir()/nonexistent/path/to という親ディレクトリのパスを正しく導出します。しかし、そのディレクトリが実際にシステム上に存在するかどうかは別問題であるため、QDir::exists() で確認することが重要です。

例 3: ディレクトリ自身の QFileInfoabsoluteDir()

QFileInfo がディレクトリ自身を表している場合、absoluteDir() はその親ディレクトリを返します。ディレクトリ自身を QDir オブジェクトとして取得したい場合は、absoluteFilePath() を使います。

#include <QCoreApplication>
#include <QFileInfo>
#include <QDebug>
#include <QDir>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // ディレクトリのパス
    QString dirPath = "/home/user/my_project/"; // Linux/macOSの場合
    // QString dirPath = "C:/Users/User/MyProject/"; // Windowsの場合

    QFileInfo dirInfo(dirPath);

    // absoluteDir() はディレクトリの「親」を返す
    QDir parentOfDir = dirInfo.absoluteDir();
    qDebug() << "ディレクトリのQFileInfoのabsoluteDir():" << parentOfDir.absolutePath();

    // ディレクトリ自身を QDir オブジェクトとして取得したい場合
    QDir actualDir(dirInfo.absoluteFilePath());
    qDebug() << "ディレクトリ自身をQDirとして:" << actualDir.absolutePath();

    return a.exec();
}

出力例

ディレクトリのQFileInfoのabsoluteDir(): "/home/user"
ディレクトリ自身をQDirとして: "/home/user/my_project"

解説
my_project ディレクトリの QFileInfo から absoluteDir() を呼び出すと、その親である /home/user が返されます。my_project ディレクトリ自身を QDir オブジェクトとして扱いたい場合は、dirInfo.absoluteFilePath() で絶対パスを取得し、それを新しい QDir オブジェクトのコンストラクタに渡すのが正しい方法です。

例 4: シンボリックリンクに対する absoluteDir() の挙動

シンボリックリンクの場合、absoluteDir()シンボリックリンク自身の親ディレクトリを返し、リンク先の親ディレクトリではありません。

#include <QCoreApplication>
#include <QFileInfo>
#include <QDebug>
#include <QDir>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 実際のファイルが存在すると仮定 (例: /data/target_files/document.txt)
    // そして、そのシンボリックリンクが /home/user/mylink.txt にあると仮定

    // (テストのためにシンボリックリンクを作成するコード)
    // QDir().mkpath("/data/target_files"); // ターゲットディレクトリの作成
    // QFile actualFile("/data/target_files/document.txt");
    // if (actualFile.open(QIODevice::WriteOnly)) {
    //     actualFile.write("This is a test document.");
    //     actualFile.close();
    // }
    // QFile::link("/data/target_files/document.txt", "/home/user/mylink.txt"); // シンボリックリンクの作成

    QString symLinkPath = "/home/user/mylink.txt"; // シンボリックリンクのパス
    QString actualTargetPath = "/data/target_files/document.txt"; // 実際のターゲットのパス

    QFileInfo symLinkInfo(symLinkPath);

    qDebug() << "シンボリックリンクのパス:" << symLinkInfo.absoluteFilePath();

    // シンボリックリンクの親ディレクトリ (リンク自身の場所)
    QDir linkParentDir = symLinkInfo.absoluteDir();
    qDebug() << "シンボリックリンクのabsoluteDir():" << linkParentDir.absolutePath();

    // リンク先のファイルの親ディレクトリを取得したい場合
    if (symLinkInfo.isSymLink()) {
        QString targetPath = symLinkInfo.symLinkTarget();
        QFileInfo targetFileInfo(targetPath);
        QDir targetParentDir = targetFileInfo.absoluteDir();
        qDebug() << "リンク先のファイルのabsoluteDir():" << targetParentDir.absolutePath();
    }

    // (テスト後にシンボリックリンクを削除するコード)
    // QFile::remove("/home/user/mylink.txt");
    // QFile::remove("/data/target_files/document.txt");
    // QDir("/data/target_files").removeRecursively();

    return a.exec();
}

出力例

シンボリックリンクのパス: "/home/user/mylink.txt"
シンボリックリンクのabsoluteDir(): "/home/user"
リンク先のファイルのabsoluteDir(): "/data/target_files"

解説
mylink.txtQFileInfo から absoluteDir() を呼び出すと、その親ディレクトリである /home/user が返されます。リンク先の実際のファイルである /data/target_files/document.txt の親ディレクトリを取得したい場合は、symLinkTarget() でリンク先のパスを取得し、それを基に新しい QFileInfo を作成してから absoluteDir() を呼び出す必要があります。



QFileInfo::path() と QString::remove() または QString::lastIndexOf() を組み合わせる

QFileInfo::path() はファイル名を含まないパス部分を返します。このパスからさらに親ディレクトリを抽出するために、文字列操作を行う方法です。

特徴

  • パスセパレータ(/\)の処理を考慮する必要がありますが、Qtは内部的に / を標準として扱うため、多くの場合は自動的に処理されます。
  • absoluteDir() のように直接 QDir オブジェクトを返さないため、その後のファイルシステム操作には追加の変換が必要になることがあります。
  • QDir オブジェクトではなく QString でパスを操作したい場合に有効です。


#include <QCoreApplication>
#include <QFileInfo>
#include <QDebug>
#include <QDir> // QDir::separator() を使用するために含める

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString filePath = "/home/user/documents/report.txt";
    QFileInfo fileInfo(filePath);

    // QFileInfo::path() はファイル名を含まないパスを返す
    QString fullPathWithoutFileName = fileInfo.path();
    qDebug() << "QFileInfo::path():" << fullPathWithoutFileName;

    // パスセパレータを探し、それ以前の部分を取得する
    // QDir::separator() は現在のOSの適切なセパレータを返す
    int lastSeparatorIndex = fullPathWithoutFileName.lastIndexOf(QDir::separator());

    QString parentDirPath;
    if (lastSeparatorIndex != -1) {
        parentDirPath = fullPathWithoutFileName.left(lastSeparatorIndex);
    } else {
        // セパレータがない場合(例: "file.txt" のようなパス)
        // この場合は、親ディレクトリは現在の作業ディレクトリになるか、
        // あるいはパスがすでにルートディレクトリを表している可能性があります。
        parentDirPath = "."; // または QDir::currentPath() など
    }

    qDebug() << "QString操作で取得した親ディレクトリ:" << parentDirPath;

    // QFileInfo::absoluteDir() と比較
    qDebug() << "QFileInfo::absoluteDir() (比較用):" << fileInfo.absoluteDir().absolutePath();

    return a.exec();
}

出力例

QFileInfo::path(): "/home/user/documents"
QString操作で取得した親ディレクトリ: "/home/user"
QFileInfo::absoluteDir() (比較用): "/home/user"

解説
QFileInfo::path()/home/user/documents を返します。そこから QDir::separator() を使って最後のスラッシュの位置を見つけ、その左側を切り取ることで親ディレクトリ /home/user を取得しています。この方法は文字列操作に慣れている場合に直感的かもしれませんが、パスの末尾のスラッシュの有無や、ファイルがルートディレクトリ直下にある場合など、エッジケースの考慮が必要です。

QDir::cdUp() を利用する

QDir オブジェクトの cdUp() 関数を使用すると、そのディレクトリを一つ上の親ディレクトリに移動させることができます。

特徴

  • パスが存在しなくても動作しますが、cdUp() はパスが存在しない場合は期待通りに動作しないことがあります(特に、存在しないディレクトリを基点とした場合)。
  • 元のパスが相対パスであっても、makeAbsolute() を事前に呼び出すことで絶対パスとして操作できます。
  • QDir オブジェクト自体を操作するため、チェーンして親ディレクトリを複数回遡ることが可能です。


#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QFileInfo>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString filePath = "/home/user/documents/report.txt";

    // まず、ファイルのディレクトリを表す QDir オブジェクトを作成
    // QFileInfo::absolutePath() を使うと、ファイル名を含まない絶対パスが得られる
    QDir currentDir(QFileInfo(filePath).absolutePath());
    qDebug() << "元のディレクトリ:" << currentDir.absolutePath();

    // cdUp() を呼び出して親ディレクトリに移動
    currentDir.cdUp();
    qDebug() << "cdUp() で移動した親ディレクトリ:" << currentDir.absolutePath();

    // QFileInfo::absoluteDir() と比較
    qDebug() << "QFileInfo::absoluteDir() (比較用):" << QFileInfo(filePath).absoluteDir().absolutePath();

    qDebug() << "--------------------";

    // QDir::cdUp() を複数回呼び出す例
    QString deeplyNestedPath = "/usr/local/bin/my_app/data/settings.json";
    QDir nestedDir(QFileInfo(deeplyNestedPath).absolutePath());
    qDebug() << "元のネストされたディレクトリ:" << nestedDir.absolutePath();

    nestedDir.cdUp(); // /usr/local/bin/my_app/data -> /usr/local/bin/my_app
    qDebug() << "1つ上の親:" << nestedDir.absolutePath();

    nestedDir.cdUp(); // /usr/local/bin/my_app -> /usr/local/bin
    qDebug() << "さらに1つ上の親:" << nestedDir.absolutePath();

    return a.exec();
}

出力例

元のディレクトリ: "/home/user/documents"
cdUp() で移動した親ディレクトリ: "/home/user"
QFileInfo::absoluteDir() (比較用): "/home/user"
--------------------
元のネストされたディレクトリ: "/usr/local/bin/my_app/data"
1つ上の親: "/usr/local/bin/my_app"
さらに1つ上の親: "/usr/local/bin"

解説
QFileInfo(filePath).absolutePath() を使って、ファイルを含むディレクトリの絶対パスを文字列として取得し、それを QDir オブジェクトのコンストラクタに渡します。その後、cdUp() を呼び出すことで、そのディレクトリの親ディレクトリに QDir オブジェクトのパスが変更されます。複数回呼び出すことで、階層を遡ることが可能です。

QDir::cleanPath() と QString::section() を組み合わせる

QDir::cleanPath() はパス内の ...、重複するセパレータなどを解決して正規化されたパス文字列を返します。これと QString::section() を組み合わせて親ディレクトリを取得することもできます。

特徴

  • 文字列操作の知識が必要です。
  • パス文字列をよりクリーンな形式にしてから操作できるため、予期せぬパス形式による問題を避けやすいです。


#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QFileInfo>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString filePath = "/home/user/./documents/../documents/report.txt"; // 余分な要素を含むパス

    // まずパスをクリーンにする
    QString cleanedPath = QDir::cleanPath(filePath);
    qDebug() << "クリーンなパス:" << cleanedPath; // "/home/user/documents/report.txt"

    // クリーンなパスからファイル名を削除
    QString pathWithoutFileName = QFileInfo(cleanedPath).path();
    qDebug() << "ファイル名を除いたパス:" << pathWithoutFileName; // "/home/user/documents"

    // 最後のセパレータで分割し、親ディレクトリ部分を取得
    // section(QChar separator, int start_index, int end_index = -1)
    // 0番目のセクションがルート、-1番目のセクションが最後の要素
    QString parentDir = pathWithoutFileName.section(QDir::separator(), 0, -2);
    qDebug() << "QString::section()で取得した親ディレクトリ:" << parentDir;

    // QFileInfo::absoluteDir() と比較
    qDebug() << "QFileInfo::absoluteDir() (比較用):" << QFileInfo(filePath).absoluteDir().absolutePath();

    // ルートディレクトリの場合の挙動
    QString rootPath = "/";
    QString cleanedRootPath = QDir::cleanPath(rootPath);
    QString rootParent = QFileInfo(cleanedRootPath).path().section(QDir::separator(), 0, -2);
    qDebug() << "ルートパスの親:" << rootParent; // 通常は空文字列またはルート自体を指す

    return a.exec();
}

出力例

クリーンなパス: "/home/user/documents/report.txt"
ファイル名を除いたパス: "/home/user/documents"
QString::section()で取得した親ディレクトリ: "/home/user"
QFileInfo::absoluteDir() (比較用): "/home/user"
ルートパスの親: ""  (システムによって '/' になることもあります)

解説
QDir::cleanPath() はパスを整形し、その後 QFileInfo::path() でファイル名を除去します。最後に QString::section() を使って、最後のセパレータを除いた部分を抽出します。これは特に、パスが複雑な場合に有効です。

QFileInfo::absoluteDir() は、ファイルの親ディレクトリを QDir オブジェクトとして簡単に取得できるため、ほとんどの場面で推奨される方法です。しかし、以下のような代替方法も存在します。

  • QDir::cleanPath() と文字列操作
    不規則なパスを処理し、正規化されたパスから親ディレクトリを抽出したい場合に役立ちます。
  • QDir::cdUp()
    QDir オブジェクトを操作してディレクトリ階層を遡りたい場合に有効です。
  • QFileInfo::path() と文字列操作
    QString としてパスを詳細に制御したい場合に適しています。