その3 相対絶対ファイルパス解析ツール
今回はあると便利なファイルパス解析ツールです。ゲームの中でディレクトリ(フォルダ)パス文字列はリソースファイルを指定する時に使います。意外と機会が多いのに煩わしく面倒なのがパスからファイル名と拡張子を分離する処理です。拡張子が無いファイル名などもあって、その処理分けでソースは大いに汚れます。またフォルダ構成をそのままにファイル名だけ取り替えたいとか、フォルダを入れ替えたり削除する必要があるとか、とにかくファイルパスというのはやりたい事が沢山あるんです。
ここではそんな相対パス文字列(及び絶対パス文字列)を解析してきっちりまとめてくれるPathStrAnalizerクラスを提供致します。
@ 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 基本的なファイルパス解析を実装