Qt (1) コンソールアプリでQtのパス制御を調べる
早速、コンソールアプリケーションを作成してみましょう
上記のsample.cppをコンパイルして、コンソールアプリを作成したいと思います。
1
2
3
4
5
6
7
8
9
| #include <iostream>
using namespace std;
int main(int /* argc */, char* /*argv[]*/ )
{
std::cout << "Test"<< std::endl;
return 0;
}
|
コンソールアプリの作成は、簡単です。
MAKEFILEの作成時にオプションをつけるだけです。
1
2
3
4
5
6
7
| C:\temp> qmake -project
C:\temp> qmake temp.pro
C:\temp> nmake
:
: -- compile...
:
C:\temp>
|
今では、上記のようにやっていたと思います。
コンソールアプリを作成する場合、2行目でMAKEファイルを作成する際の"qmake"へオプションを指定してあげます。
1
| C:\temp> qmake temp.pro "CONFIG+=console"
|
"CONFIG+=console"を追加してあげるだけです。
後は、同じように"nmake"を実行して、コマンドラインから、実行ファイルを起動してみてください。
きっと、"Test"と表示されると思います。
また、VC++のプロジェクトファイルを作成する場合も同じように、
"CONFIG+=console"を追加してあげるだけです。
1
| C:\temp> qmake -tp vc temp.pro "CONFIG+=console"
|
このように指定すれば、コンソールアプリケーションが作成できます。
コンソール以外も、このようなやり方で、"dll"(DLL),"static"(ライブラリ)などを作成することができます。
詳しくは、
http://doc.trolltech.com/4.5/qmake-variable-reference.html#config
を参照してください。CONFIGに設定できるオプションパラメータについて記載されています。
前準備ができました。
Qtでのパス管理を調べる
続けて、Qtでのパス管理は、どうなっているでしょうか?
Qtでは、QDir,QFileInfoクラスで、ほとんどのパス制御を行っています。
では、以下のソースコードで調べてみましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| #include "QFileInfo"
#include "QTextStream"
int main(int argc , char* argv[] )
{
QTextStream out(stdout);
int ni;
// print of input parameters.
for ( ni = 0; ni < argc; ni++ ){ // app.argc() == argc
out << "argv[" << ni << "]:" << argv[ni] << endl;
}
if(argc>1){
// secound parameter is check path.
QFileInfo fInfo(QString::fromLocal8Bit(argv[1]));
out << "finfo absoluteFilePath() = " << fInfo.absoluteFilePath() << endl;
out << "finfo absolutePath() = " << fInfo.absolutePath() << endl;
out << "finfo baseName() = " << fInfo.baseName() << endl;
out << "finfo canonicalFilePath() = " << fInfo.canonicalFilePath() << endl;
out << "finfo canonicalPath() = " << fInfo.canonicalPath() << endl;
out << "finfo completeBaseName() = " << fInfo.completeBaseName() << endl;
out << "finfo completeSuffix() = " << fInfo.completeSuffix() << endl;
}
}
|
IOストリームが、STLのiostreamからQt用のQTextStreamへ変わったことに注意してください。
QFileInfoの各メソッドは、以下のとおりです。詳細については、クラスドキュメントを参照してください。
- absoluteFilePath : フルパス名(ファイル名を含む)を出力します
- absolutePath : フルパス名(ファイル名を含まず)を出力します
- baseName : ファイル名の拡張子なしの名前を出力します
- canonicalFilePath : フルパス名(ファイル名を含む)を出力します
(実際にファイルが存在しないと出力されません)
- canonicalPath : フルパス名(ファイル名を含まず)を出力します
(実際にファイルが存在しないと出力されません)
- completeBaseName : ファイル名の拡張子なしの名前を出力します
-- baseNameとの違いは、"."が複数あるファイル名の場合の動作が異なります。
- baseNameでは、最初の"."より左を取得し、completeBaseNameは、最後の"."より左を取得します。
- completeSuffix : ファイル名の拡張子の名前を出力します
クラスドキュメント:
1
2
3
4
5
6
7
8
9
10
| c:\temp> temp.exe "c:\temp\temp.txt"
argv[0]:temp.exe
argv[1]:c:\temp\temp.txt
finfo absoluteFilePath() = C:/temp/temp.txt
finfo absolutePath() = C:/temp
finfo baseName() = temp
finfo canonicalFilePath() = C:/temp/temp.txt
finfo canonicalPath() = C:/temp
finfo completeBaseName() = temp
finfo completeSuffix() = txt
|
このように、Windowsと異なり、"/"でのパス管理がされています。また、ドライブ名は、全て大文字で管理されます。
では、ショートファイル(パス)名は、どう管理されるでしょうか?
実際に調べてみましょう。結果は、以下のとおりです。
1
2
3
4
5
6
7
8
9
10
| c:\temp> temp.exe "C:\PROGRA~1\MICROS~1.0\VC\BIN\cl.exe"
argv[0]:temp.exe
argv[1]:C:\PROGRA~1\MICROS~1.0\VC\BIN\cl.exe
finfo absoluteFilePath() = C:/PROGRA~1/MICROS~1.0/VC/BIN/cl.exe
finfo absolutePath() = C:/PROGRA~1/MICROS~1.0/VC/BIN
finfo baseName() = cl
finfo canonicalFilePath() = C:/PROGRA~1/MICROS~1.0/VC/BIN/cl.exe
finfo canonicalPath() = C:/PROGRA~1/MICROS~1.0/VC/BIN
finfo completeBaseName() = cl
finfo completeSuffix() = exe
|
ショートファイル(パス)名は、そのままの名前で管理されています。では、ロングファイル(パス)名はどうでしょう?
同じように、実際に調べてみましょう。結果は、以下のとおりです。
1
2
3
4
5
6
7
8
9
10
| c:\temp> temp.exe "C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\cl.exe"
argv[0]:temp.exe
argv[1]:C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\cl.exe
finfo absoluteFilePath() = C:/Program Files/Microsoft Visual Studio 9.0/VC/bin/cl.exe
finfo absolutePath() = C:/Program Files/Microsoft Visual Studio 9.0/VC/bin
finfo baseName() = cl
finfo canonicalFilePath() = C:/Program Files/Microsoft Visual Studio 9.0/VC/bin/cl.exe
finfo canonicalPath() = C:/Program Files/Microsoft Visual Studio 9.0/VC/bin
finfo completeBaseName() = cl
finfo completeSuffix() = exe
|
ロングファイル(パス)名も、そのままの名前で管理されています。
では、ショートファイル(パス)名とロングファイル(パス)名のそれぞれのファイルは、同じと認識されるでしょうか?
以下のソースで確認してみましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| #include "QFileInfo"
#include "QTextStream"
int main(int argc , char* argv[] )
{
QTextStream out(stdout);
int ni;
// print of input parameters.
for ( ni = 0; ni < argc; ni++ ){ // app.argc() == argc
out << "argv[" << ni << "]:" << argv[ni] << endl;
}
if(argc>2){
// secound parameter is check path.
QFileInfo fInfo1(QString::fromLocal8Bit(argv[1]));
QFileInfo fInfo2(QString::fromLocal8Bit(argv[2]));
out << "finfo check = " << (fInfo1 == fInfo2) << endl;
}
}
|
1
2
3
4
5
| c:\temp> temp.exe "C:\PROGRA~1\MICROS~1.0\VC\BIN\cl.exe" "C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\cl.exe"
argv[0]:temp.exe
argv[1]:C:\PROGRA~1\MICROS~1.0\VC\BIN\cl.exe
argv[2]:C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\cl.exe
finfo check = 0
|
一致しません。同じようにQDirでもチェックしてみましょう。
先のサンプルソースのQFileInfoをQDirへ変更して実施してみましょう。
結果は同じです。
このようにQtでは、ショートパス、ロングパスは別物として扱われます。
もし、このアプリケーションで、パスのチェックが必要な場合は、そのアプリで対応するしかありません。
例えば、以下のようにアプリケーションでは、常にロングパスのみで管理するようにすれば、この問題が回避できるでしょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| #include "QFileInfo"
#include "QTextStream"
#ifdef Q_OS_WIN
#include <windows.h>
QString getLongPathName(const QString& spath)
{
ushort uspath[MAX_PATH];
if (spath.isEmpty()){
return QString();
}
QString spath_win32 = QDir::toNativeSeparators(spath);
if(GetLongPathName(spath_win32.utf16(), uspath, MAX_PATH)==0){
return spath;
} else {
return QDir::fromNativeSeparators(QString::fromUtf16 (uspath));
}
}
#else
QString getLongPathName(const QString& spath)
{
return spath;
}
#endif
int main(int argc , char* argv[] )
{
QTextStream out(stdout);
int ni;
// print of input parameters.
for ( ni = 0; ni < argc; ni++ ){ // app.argc() == argc
out << "argv[" << ni << "]:" << argv[ni] << endl;
}
if(argc>2){
// secound parameter is check path.
QFileInfo fInfo1(getLongPathName(QString::fromLocal8Bit(argv[1])));
QFileInfo fInfo2(getLongPathName(QString::fromLocal8Bit(argv[2])));
out << "finfo check = " << (fInfo1 == fInfo2) << endl;
}
}
|
このプログラムで検証してみましょう。結果は、以下のとおりです。
1
2
3
4
5
| c:\temp> temp.exe "C:\PROGRA~1\MICROS~1.0\VC\BIN\cl.exe" "C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\cl.exe"
argv[0]:temp.exe
argv[1]:C:\PROGRA~1\MICROS~1.0\VC\BIN\cl.exe
argv[2]:C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\cl.exe
finfo check = 1
|
このようにQtでは、Windows固有の問題も少なからずあります。(そんなに多くはありません。なにせ、Qtはクロスプラットフォーム対応なのですから。)
今回は、その一例のディレクトリとファイル名について書きました。
また、Qtのライブラリについても、少し、さわりだけ触れました。Qtのライブラリは、使えば使うほど味がでてきます。
一度、試されると良いと思います。
もっと、Qt関連について詳しく知りたい方は、以下の本なども良いと思います。
Qtに関する日本語の本が少ないですね。「入門書」は、さすがに、このページを読まれるくらいの方は不要だと思います。
やっぱり、本+ネット+試してみる!!の3本柱でやっていく以外にないように思います。
コメントをどうぞ