OSTRACISM CO.
C#とObjective-CとJavaと...
設定保存
一般的にアプリケーションは前回使ったときの状態のいくらかを保持して次回起動時に反映するという動作をする。昔のWindows 3.1の頃はウィンドウ位置を覚えてくれるアプリケーションが少なかった。システム付属の電卓でさえウィンドウ位置を覚えてくれなかった。ウィンドウ位置を記録することが使い勝手にとっていかに重要かの認識がMicrosoftにはなかったのであろう。確認するとWindows XPの電卓もウィンドウ位置を覚えてくれない。何考えてんだ。
当時のMacintoshの電卓はウィンドウ位置を覚えてくれたが、自分のダイアログ(だったかウィンドウだったかの)リソースの書き換えというあぶなっかしい実装だった。しかもSystem 6までのDA(デスクアクセサリ)はシステムファイルに入っているのでかなり危険であった。当時のMacintoshはかなり壊れやすいシステムであった。
System 6の頃Macintoshにおいて多くのアプリケーションは設定情報のファイルをシステムフォルダに勝手に保存していた。自アプリケーションのあるフォルダ内に設定ファイルを保存するアプリケーションもあった。ともかくなんら統一性はなかった。
MacintoshはSystem 7になり、Preferences(初期設定)というフォルダがシステムフォルダ内に用意され、ともかくそこに設定ファイルを保存しようということになった。PreferencesフォルダのディレクトリIDを得るAPIがあるにもかかわらず、日本語のシステムにPreferencesというフォルダを勝手に作る行儀の悪いアプリもときどきあったが、これで概ねシステムの移行が楽になったのは事実である。
Windows 3.1において設定保存はシステムディレクトリにあるWIN.INIファイルを使うという、かなり怪しい方法だった。一応APIはあったが、全アプリで1ファイルとはなんとも豪儀である。MacintoshのSystem 6と同じくシステムや自アプリケーションのあるディレクトリに独立した設定ファイルを保存するアプリケーションの方が一般的だったかもしれない。
Windows 95においてレジストリが導入され(実際はWindows NT 3.1から)、統一的な設定保存の改善がなされた。しかし、階層化されているとはいえこれも1ファイルでしかなく、Macintoshのようなシステムの移行の便宜なんてのは一切考慮されていない(むしろ難しくなった)。
Windows NTではシステムの定めるユーザのホームディレクトリが用意され、各アプリケーションのデータはそこのApplicationDataディレクトリ等に保存できるようになっている。しかし、このディレクトリをAPIで得ることができるわけではなく、HOMEPATH環境変数から自力でパスを組み立てる必要がある。とはいえレガシーWindows(95/98)も考慮に入れるアプリケーションはレジストリを使うしかなかった。
C#
static string GetSettingDirPath() {
return Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "OSTRA");
}
static string GetSettingFilePath() {
return Path.Combine(GetSettingDirPath(), "GGG4W.setting");
}
public bool Ending() {
bool result = false;
string dir = GetSettingDirPath();
if (Directory.Exists(dir) == false) {
Directory.CreateDirectory(dir);
}
XmlSerializer serializer = new XmlSerializer(typeof(TSetting));
FileStream fs = new FileStream(GetSettingFilePath(), FileMode.Create);
if (fs != null) {
serializer.Serialize(fs, this);
fs.Close();
result = true;
}
return result;
}
ユーザのホームディレクトリのApplicationDataディレクトリ等を得るメソッドがSystem.Environment.GetFolderPathである。パラメタにより他のディレクトリも得ることができる。自力で環境変数を見に行く必要はないが、これは.NETが環境変数から組み立てているのだろうと推察される。
また、.NETにはクラスのシリアライズ機能を持つXmlSerializerクラスがあり、Serializeメソッドにより個々のメンバを気にすることなくXML化できる。
Objective-C
CarbonではSystem 7以来のPreferencesフォルダを得るAPIがまだ有効となっている。
Cocoaでは一歩先に行っており、アプリケーション毎にPreferencesのファイル名が自動的に決まり、そのファイルをデフォルトの設定ファイルとしている。
- (void)ending {
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
version = CURRENT_PREF_VERSION;
[ud setInteger:version forKey:@"version"];
[ud setObject:targetFilePath forKey:@"targetFilePath"];
[ud setObject:topDirPath forKey:@"topDirPath"];
[ud setObject:indexFilePath forKey:@"indexFilePath"];
[ud setInteger:bits forKey:@"bits"];
[ud setInteger:matchRate forKey:@"matchRate"];
[ud setInteger:pixelNumber forKey:@"pixelNumber"];
[ud setInteger:searchMethod forKey:@"searchMethod"];
[ud synchronize];
}
デフォルト設定のファイル名はInfo.plistのCFBundleIdentifireの値に.plistを付けたもの。NSUserDefaultsクラスのstandardUserDefaultsで得たインスタンスに対して入出力することで自動的にデフォルトの設定ファイルを利用できる。
生成される.plistは本来はXMLなのだが、Mac OS X 10.4ではなんらかのバイナリ形式になっている。いや、それ以前からかもしれないが気づかなかった。システム全体のスループット向上には良いのではあろう。
NSUserDefaultsクラスには基本型やクラスの入出力のメソッドが用意されている。
Java
boolean ending() {
File f = null;
FileOutputStream stream = null;
try {
f = new File(m_settingFilePath);
if (f == null)
return false;
stream = new FileOutputStream(f);
if (stream == null)
return false;
Properties prop = new Properties();
version = CURRENT_PREF_VERSION;
prop.setProperty("version", String.valueOf(version));
prop.setProperty("locationX", String.valueOf(locationX));
prop.setProperty("locationY", String.valueOf(locationY));
prop.setProperty("windowHeight", String.valueOf(windowHeight));
prop.setProperty("windowWidth", String.valueOf(windowWidth));
prop.setProperty("targetFilePath", targetFilePath);
prop.setProperty("topDirPath", topDirPath);
prop.setProperty("indexFilePath", indexFilePath);
prop.setProperty("bits", String.valueOf(bits));
prop.setProperty("matchRate", String.valueOf(matchRate));
prop.setProperty("pixelNumber", String.valueOf(pixelNumber));
prop.setProperty("searchMethod", String.valueOf(searchMethod));
prop.setProperty("grephicViewer", grephicViewer);
prop.store(stream, "GGG4J");
}
catch (Exception e) {
return false;
}
try {
if (stream != null)
stream.close();
}
catch (Exception e) {
}
return true;
}
Javaはマルチプラットフォームであるが故に、統一された場所への設定保存の方法は望むべくもない。でも設定保存のためのPropertiesクラスが用意されている。
Propertiesクラスによる保存ファイルは.NETやCocoaと違いXMLではなく、Windows 3.1の.iniファイルに近い。Java 1.5からはXMLでの保存もサポートされたが1.4が主流のうちは使えない機能であろう。
Propertiesクラスで保存できるのは文字列だけなので、数値等を文字列に変換するのはプログラム側の責任になる。
2005.07.16
2005.09.18
「インデックス」へ戻る
OSTRACISM CO.
OSTRA / Takeshi Yoneki