ホーム < ゲームつくろー! < ツール編

その3 相対絶対ファイルパス解析ツール


 今回はあると便利なファイルパス解析ツールです。ゲームの中でディレクトリ(フォルダ)パス文字列はリソースファイルを指定する時に使います。意外と機会が多いのに煩わしく面倒なのがパスからファイル名と拡張子を分離する処理です。拡張子が無いファイル名などもあって、その処理分けでソースは大いに汚れます。またフォルダ構成をそのままにファイル名だけ取り替えたいとか、フォルダを入れ替えたり削除する必要があるとか、とにかくファイルパスというのはやりたい事が沢山あるんです。

 ここではそんな相対パス文字列(及び絶対パス文字列)を解析してきっちりまとめてくれるPathStrAnalizerクラスを提供致します。

ツール名 ファイルパス解析ツール
名前空間 Dix
クラス名 PathStrAnalizer
公開メソッド PathStrAnalizer( TCHAR* pathName = 0 )
pathName  : パス名
コンストラクタ
相対ファイルパス、絶対ファイルパスを登録できる
PathStrAnalizer() 非同期読み込みを開始する
読み込み成功ならtrue、失敗ならfalseを返す
bool deleteDirectory( size_t level )
level   : ディレクトリ階層番号
登録したディレクトリの指定階層を削除する
指定階層があればtrue、無ければfalseを返す
const TCHAR* getDirectoryName( size_t level ) const
level   : ディレクトリ階層番号
登録したディレクトリの指定階層の名前を取得する
指定階層があればtrue、無ければfalseを返す
size_t getDirectoryNum() const ディレクトリ階層数を取得する
絶対パスの場合ドライブも含められる
(例)
c:/Root/Src/Test.h → 3階層
const TCHAR* getExtName() const 拡張子名を取得する
拡張子が無い場合は空文字列が返る
const TCHAR* getFileName() const ファイル名を取得する
拡張子は含まれないので注意
const TCHAR* getFullFileName() const フルファイル名を取得する
ファイル名+拡張子の形式で出力される
const TCHAR* getFullPathName() const フルパス名を取得する
ディレクトリデリミタは「/」となる
bool insert( size_t level, const TCHAR* directoryName )
level   : ディレクトリ階層番号
directoryName   : ディレクトリ名
指定の階層にディレクトリを挿入する
絶対パスの場合、ドライブ名は変更できない
bool isAbsolutePath() 登録したパスが絶対パスかを調べる
絶対パスならばtrue、相対パスならばfalseが返る
bool regist( const TCHAR *pathName )
pathName   : パス名
相対ファイルパス、絶対ファイルパスを登録する
正しいパスが登録された場合はtrue、パスにエラーがある場合はfalseが返る
bool setDirectoryName( size_t level, const TCHAR* directoryName )
level   : ディレクトリ階層番号
directoryName   : ディレクトリ名
指定の階層番号に該当するディレクトリ名を変更する
絶対パスの場合0番目のドライブ名は変更できない。
変更に成功した場合はtrue、そうでない場合はfalseが返る。
bool setDriveName( TCHAR driveName )
driveName   : ドライブ名
絶対パスを登録した時にドライブ名を変更する
(例)
Dドライブに変更
obj.setDriveName( L'D' );
ドライブ名はアルファベット(大文字、小文字)の1文字のみを指定できる。
正しく変更できた場合はtrue、そうでない場合はfalseを返す。
bool setExtName( const TCHAR* extName )
extName   : 拡張子名
拡張子名を変更する
拡張子名は「txt」などとしドットは付けない事。
正しく登録できた場合はtrue、そうでない場合はfalseを返す。
bool setFileName( const TCHAR* fileName )
bool setFileName( const TCHAR* fileName, size_t size )
fileName   : ファイル名
szie   : 読み取りサイズ
ファイル名を変更する
拡張子を含めない事。
正しいファイル名を登録できた場合はtrue、そうでない場合はfalseを返す。
bool setFullFileName( const TCHAR* fileName )
fileName   : フルファイル名
フルファイル名を変更する
拡張子を含めたファイル名を引数に渡す。
正しいフルファイル名を登録できた場合はture、そうでない場合はfalseを返す。
bool validatePathName() 最後に登録したパスの妥当性を調べる
妥当な場合はtrue、そうでない場合はfalseを返す
バージョン v1.00 (2007. 9. 17)
ファイル PathStrAnalizer.h, PathStrAnalizer.cpp



@ PathStrAnalizerの使い方

○ パスの登録

 1つのPathStrAnalizerオブジェクトに対して相対パス及び絶対パスのどちらの形式でも登録できます。一度登録すると前の登録情報は削除されます。登録するにはコンストラクタでパス文字列を渡すかregistメソッドを利用します:

パスの登録
PathStrAnalizer PSA( _T("Resource\Picture\Scene\character_runninng_01.png") );
if( PSA.regist( _T("Resource\Picture\Scene\character_runninng_02.png") ) ) {
   // 正しい登録
}
else {
   // パス名が間違っている
}

ディレクトリデリミタは「\」も「/」も混合して使えます:

パスの登録
PathStrAnalizer PSA( _T("C:\MyGame/Resource\Picture\Scene/character_runninng_01.png") );

ただし、内部ではすべて「/」で管理されます。

 正しいパス名以外は登録出来ない仕組みにしています。正しいパス名とは、

@ c:\MyFolder/src/test.h
A c:/MyFolder/src\test
B MyFolder/src\test2.cpp
C MyFolder\src/test2

のいずれかです。これ以外に、例えば「//」となっていたり「c:MyFolder」などは認められません。また、ファイル名は必ず必要です。フォルダ名及びファイル名には「\ / ? : * " | < >」の文字は使えません。

 登録したパスの妥当性はvalidatePathNameメソッドでチェックできます:

パス名は正しい?
if ( PSA.validatePathName() ) {
   // 正しい登録
}
else{
   // 登録したパス名が間違っている
}

 これはコンストラクタでの登録と併用する事になるかと思います。


○ パス名の取得

 正しく登録されたパス名はgetPathNameメソッドで出力する事も出来ます。ディレクトリデリミタは「/」に変換されます:

パス名を取得
const TCHAR *pathName = PSA.getFullPathName();

文字列へのポインタが返される事から、もしこのパス名を保存する必要がある場合は文字列コピーが必要となります。ポインタで持っているとメソッドの仕様により参照先の状態が変わってしまうので注意です。



○ フルファイル名・ファイル名・拡張子名の取得設定

 PathStrAnalizerクラスではファイル名を「フルファイル名(test.dat)」、「ファイル名(test)」そして「拡張子名(dat)」と区別しました。各文字列を取得・設定する操作は次の通りです:

ファイル名操作
PSA.setFullFileName( _T("OtherFileName.txt") );    // フルファイル名を取替え
const TCHAR *FullFileName = PSA.getFullFileName();    // フルファイル名を取得

// ファイル名のみを取替え
//   OtherFileName.txt -> SceneFileName.txt
PSA.setFileName( _T("SceneFileName") );

// ファイル名のみを取得
const TCHAR *FileName = PSA.getFileName();

// 拡張子のみを取替え
//   SceneFileName.txt -> SceneFileName.dat
PSA.setExtName( _T("dat") );

// 拡張子のみを取得
const TCHAR *ExtName = PSA.getExtName( false );   // [.]を付けたい場合はfalse

 setFullFileNameメソッドには拡張子付きのフルファイル名を渡します。拡張子が無い場合は「拡張子無しファイル」として再登録され、拡張子情報が無くなります。また例えば「TestData.bmp.png」のようにダブル拡張子になっている場合は、「.png」が拡張子、「TestData.bmp」がファイル名として扱われます。

 setFileNameメソッドには拡張子を除いた部分を登録します。ここに拡張子がついたファイルを指定すると拡張子もファイル名として扱われてしまうので注意です。

 setExtNameメソッドは拡張子を登録します。「.」は付けません。



○ ディレクトリ名の取得

 ディレクトリ名は階層番号を指定して取得できます:

ディレクトリ名の取得
size_t directoryNum = PSA.getDirectoryNum();
for ( i = 0; i < directoryNum; i++ ) {
   const TCHAR* DirectoryName = PSA.getDirectoryName( i );
}

登録されているディレクトリの階層数はgetDirectoryNumメソッドで取得できます。上はディレクトリ階層をルートから1つずつ取得している例です。



○ ディレクトリの挿入、変更、削除

 登録したディレクトリに対しては挿入や変更・削除ができます。これはフォルダ構成を変更する時に使えます:

ディレクトリの挿入、変更、削除
// C:/    : 0番ディレクトリ
// Game   : 1番ディレクトリ
PathStrAnalizer PSA( _T("C:/Game/test.png") );

// 挿入
PSA.insert( 1, _T("Root") );  // C:/Root/Game/test.png
PSA.insert( 3, _T("Directory") );  // C:/Root/Game/Directory/test.png
PSA.insert( 10, _T("err") );  // エラー
PSA.insert( 0, _T("err") );  // 絶対パスの場合はエラー

PathStrAnalizer PSA_rel( _T("Game/test.png") );
PSA_rel.insert( 0, _T("good") );  // good/Game/test.png (相対パスの先頭挿入は有効)

// 変更
PSA.setDirectoryName( 2, _T("D-01") );   // C:/Root/D-01/Directory/test.png
PSA.setDirectoryName( 1, _T("First") );  // C:/First/D-01/Directory/test.png
PSA.setDirectoryName( 0, _T("err") );    // ドライブ変更は無効

// 削除
PSA.deleteDirectory( 3 );  // C:/First/D-01/test.png
PSA.deleteDirectory( 1 );  // C:/D-01/test.png
PSA.deleteDirectory( 1 );  // C:/test.png
PSA.deleteDirectory( 0 );  // エラー

 各メソッドは第1引数でディレクトリ番号を指定します。絶対パスの場合はドライブ名もディレクトリ番号に含まれますが、上記のメソッドでドライブ名は変更できません。ドライブ名の変更にはsetDriveNameメソッドを用います。

 挿入は「フォルダ名が指定先番号になるように」挿入されます。D01/D02/D03/test.hというパス名に対して2番に「Insert」を挿入した場合、新しいパス名は、D01/D02/Insert/D03/test.hとなります。

 deleteDirectoryメソッドで絶対パスの場合、ドライブ削除(0番目削除)は出来ません。相対パスならば0番目のルートディレクトリも削除できます。



A バージョン情報

2007/ 9/ 18
v1.00 基本的なファイルパス解析を実装