プログラマーズマガジン Windowsでのファイル操作2



1.パス名


 Windowsでは従来のDOSとは異なり、UNIXファイルシステムのように長いファイル名 を使えるようになりました。これに伴いコンパイラのインクルードファイルに定義され ている最大ファイルサイズなども変更になりました。
	MAXPATH、_MAX_PATH	80 -> 260
	MAXDIR、_MAX_DIR	66 -> 256
	MAXFILE、_MAX_FILE	9 -> 256
	MAXEXT、_MAX_EXT	4 -> 256
また、使用できる文字の種類も増えWindowsユーザにとって非常に大きなメリットに なりました。しかし、DOS/16bit Windowsのプログラムを移植しなければならない プログラマには少なからず頭痛の種となっているのではないでしょうか。
 プログラマにとって問題となる項目としては次の4点があげられるとおもいます。
(1)長いファイル名が使える。
(2)ピリオド'.'がファイル内に複数存在しうる。
(3)ファイル名に空白文字が使える。
(4)ファイル/ディレクトリの作成時に大小文字が区別される

(1)長いファイル名への対応は比較的簡単です。常識的なプログラムならば ファイル名を格納する配列のサイズ指定にはMAXPATHなどの定義を使用しているので この対応は再コンパイルするだけの場合もあります。しかし、サイズに数字を記述 してある非常識なプログラムでも配列の定義を機械的に変えるだけなのでたいした 手間ではないでしょう。

(2)この変更も_splitpath()などの関数を使っていれば問題ありません。しかし、 ファイル名の先頭からピリオドをサーチそれ以降を拡張子として何かするような 処理はうまく動作しません。

(3)これは最大の頭痛の原因になります。パス名に空白を使う人なんかほとんどいないに 決まっていると自分に言い聞かせて空白文字は未対応にしてしまいたくなるような アプリケーションもあるでしょう。しかし、Windowsは最初からルートディレクトリに "Program Files"という空白文字を含むディレクトリを作成してしまうのでやはり空白 文字への対応は必用でしょう。 空白文字への対応は、いろいろなパターンでバグが発生すると 考えられるので各アプリケーションごとに十分なテストをする必用があります。 考えられる例をいくつかあげてみます。
・CUIベースのインターフェイスウィンドウが用意されている場合
・WinMain()のlpszCmdLineからファイル名を得ている
・ファイル名の最後の空白をカットしている場合
・内部でファイル名を含むコマンド列(区切り文字に空白を使用)を作成してから処理関数に渡している場合
あまり定型的なケースが思い付きませんが参考にしてください。一方、ダイアログボックスなどから ファイル名を入力してオープンするようなアプリケーションではほとんど改造の必用が ありません。

(4)ファイル/ディレクトリ作成時に指定した名前の大小文字は有効ですが、ファイルの オープン時には大小文字の違いは無視されます。また、同じディレクトリに 名前の大小だけをかえた(makefileとMakefileのように)ファイルやディレクトリは 作成できません。入力したファイルを内部で大(小)文字に変換してから表示するような アプリケーションはパスの実際の大小文字とおりに表示するように変更するべきでしょう。 大(小)文字への変換のような処理を削除する場合は、ファイル名のチェックにstrcmp() などを使っていないか調べstricmp()などに変更する必用があります。
 これらの変更にどうしても対処できないアプリケーションはGetShortPathName()を使って 逃げることができるかもしれません。GetShortPathName()はロングファイル名から DOSウィンドウのDIRコマンドで左側に表示される8+3形式のファイルへの変換を行って くれます。ただし、変換してくれるのは(ファイル名だけではなく)フルパス名なので 注意してください。
	if(GetShortPathName(long_path, short_path, MAXPATH) != 0){
		printf("%s -> %s\n", long_path, short_path);
	}

2.カレントディレクトリ


 Windowsでもカレントディレクトリが存在しますが、OS自体はDOSのように ディスクごとにカレントディレクトリを保持してくれないようです。 DOSウィンドウでドライブをかえて試してみるとちゃんと動作するのですが、 環境変数に情報を書き込んでいます。setコマンドで見ただけではこの設定は 表示されないので次のようなテストプログラムを作成し起動してみます。
#include <windows.h>
#include <stdio.h>

main()
{
	unsigned char
		*env_str,
		buff[128];

	env_str = GetEnviromentString();
	for(; *env_str; env_str++){
		while(*env_str){
			buff[0] = (unsigned char)(*env_str++);
			buff[1] = '\0';
			printf("%s", buff);
		}
		printf("\n");
	}
}
実行結果
=C:=C:\source\test
=D:=D:\abc\def
	.
	.
	.
DOSウィンドウで移動したドライブに関する情報が環境変数に記録されているのが わかります。