ホーム

OFF-SOFT.net

OFF-SOFT.net

ウェブやソフトウェアに関するサポート&情報サイトです。サイト構築からソフトウェアの作成、利用まであなたの助けになるかも・・・・しれません。たぶん・・。

Qt (1) コンソールアプリでQtのパス制御を調べる

公開日| 2009年05月20日 | コメントはまだありません。
概要 :
 Qtでの環境設定が、先日までの記事で、ほぼできました。
 ようやく、プログラミングです。今まで、"Hello World"のサンプルソースをベースに色々と試してきました。 Qtは、そもそもGUIライブラリなので、今までのやり方では、全て、GUIの実行ファイルが作成されました。これが標準だと思います。

Qtでの開発を行っていると、簡単なライブラリの使用方法などを確認したいときがあります。そのとき、GUIでなく、コンソールで、 さっと確認したくなるときがあります。

では、どうやればQtでコンソールアプリケーションが作成できるでしょう?

今回は、Qtでコンソールアプリケーションを作成し、Qtでのファイルパスの管理方法とWindows特有のファイル名(ロングパス、ショートパス)の制御について、 触れたいと思います。

関連記事: qmake でVC++ 2008 Expressのプロジェクトファイルを作成する
関連サイト: http://doc.trolltech.com/4.5/qmake-variable-reference.html#config

ここで使用したサンプルソースコード:

早速、コンソールアプリケーションを作成してみましょう
上記の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本柱でやっていく以外にないように思います。


コメント

コメントをどうぞ







  • はてなブックマークへ追加する
  • Facebookでシェアする
  • twitter でつぶやく
  • Google Plusでシェアする
  • Pocketでシェアする
ページトップへ