目次
はじめに
C++でファイルパスを扱う際、「./sub/file.txt
」のようなカレントディレクトリからの相対パスを、「C:\Users\Username\Documents\sub\file.txt
」のような完全な絶対パスに変換したい場面があります。
C++17で導入された <filesystem>
ライブラリは、この変換を行うための便利な関数を提供しています。この記事では、3つの主要なパス変換関数、absolute
, canonical
, weakly_canonical
の使い方と、それぞれの挙動の違いについて解説します。
【前提】C++17とは?
C++17は、2017年に正式化されたC++言語の規格です。<filesystem>
ライブラリはこのC++17で導入されたため、利用するにはC++17に対応したコンパイラと、適切なコンパイラ設定(および、一部の環境ではリンカ設定)が必要になります。
パス変換関数のサンプルコード
このコードは、カレントディレクトリに一時的なファイルを作成し、そのファイルへの相対パスに対して3つの異なる変換関数を適用し、結果を比較します。
完成コード
#include <iostream>
#include <filesystem>
#include <fstream>
// filesystem名前空間のエイリアス
namespace fs = std::filesystem;
int main() {
// テスト用のファイルを作成
std::ofstream("tempfile.txt");
fs::path relative_path = "./tempfile.txt";
std::cout << "元の相対パス: " << relative_path << std::endl;
std::cout << "----------------------------------" << std::endl;
// 1. absolute(): 単純に絶対パスに変換
std::cout << "absolute(): " << fs::absolute(relative_path) << std::endl;
// 2. canonical(): 正規化された絶対パスに変換 (ファイルが存在する必要あり)
std::cout << "canonical(): " << fs::canonical(relative_path) << std::endl;
// 3. weakly_canonical(): 正規化された絶対パスに変換 (ファイルが存在しなくてもOK)
fs::path non_existent_path = "./dummy/../other.txt";
std::cout << "weakly_canonical(): " << fs::weakly_canonical(non_existent_path) << std::endl;
// テスト用のファイルを削除
fs::remove("tempfile.txt");
return 0;
}
各関数の解説
1. std::filesystem::absolute(path)
- 機能: 最も基本的な変換関数です。引数で渡されたパスが相対パスであれば、カレントディレクトリのパスと結合して、絶対パスを生成します。
- 特徴:
- パスの正規化(
.
や..
の解決)は行いません。 - パスに対応するファイルやディレクトリが存在しなくても、エラーにはなりません。
- パスの正規化(
2. std::filesystem::canonical(path)
- 機能:
absolute
の機能に加え、パスの正規化も行います。正規化とは、.
(カレントディレクトリ)や..
(親ディレクトリ)を取り除き、最も短く、一意なパス表現にすることです。 - 特徴:
- 返されるパスは、常に正規化された(回り道のない)絶対パスになります。
- 【重要】 パスに対応するファイルやディレクトリが実際に存在しないと、エラー(例外)をスローします。
3. std::filesystem::weakly_canonical(path)
- 機能:
canonical
と同様に、パスの正規化を行いますが、エラーの扱いが異なります。 - 特徴:
- パスに対応するファイルやディレクトリが存在しなくても、エラーにはなりません。存在しない部分も含めて、可能な限りパスを正規化しようと試みます。
dummy/../other.txt
はother.txt
に正規化されます。
まとめ
関数 | 絶対パス化 | 正規化 | ファイルの存在 | 主な用途 |
absolute | ◯ | ☓ | 不要 | 単純な絶対パスの取得 |
canonical | ◯ | ◯ | 必要 | 既存ファイルへの一意なパスの取得 |
weakly_canonical | ◯ | ◯ | 不要 | これから作成するファイルパスの整形など |
結論として、パスの正規化(.
や ..
の解決)まで行いたい場合は canonical
または weakly_canonical
を、単純に絶対パスが欲しいだけであれば absolute
を使う、という使い分けになります。