初期設定の読み書き
Posted feedbacks - Nested
Flatten Hidden「初期設定」というのがなにを想定しているのか全くわからないです。出題の意図も見えません。もうすこし具体的な設定にならないでしょうか。
java.util.prefs.Preferencesでググってきました。どうやら、アプリケーション固有の設定情報(httpd.confや.vimrcのような)を読み書きするものらしいと理解しました。
というわけで、WindowsではINIファイルやレジストリ ("HKCUSoftware会社名アプリ名"以下)を専用のAPIで扱えば題意を満たすと考えました。この投稿では、Win16の老害、INIファイルを読み書きするGetPrivateProfileStringとWritePrivateProfileString関数を使っています。言語はActiveBasic 4です。
プログラムの内容は、(保存してある)前回のコマンドライン引数を表示した後、今回のコマンドライン引数を保存するというものです。ただし、初回起動時には(none)と表示されます。このプログラムで、例えばmyapp.exe hoge foo barと実行すると、次のようなMYAPP.INIが作成されます:
[option] LastCommandLineArgs=hoge foo bar
なお、ファイル名は必ず絶対パスで指定します。そうしないと、Windowsディレクトリを基準とした相対パスになるはずです。NT系だとユーザ別のフォルダ(Document and Settings以下)になったような気もします。
さらに余談ですが、Program Files以下へインストールされるアプリでは、実行ファイルと同じフォルダにINIを置いてはいけません。それをやると、いかにもVistaでまともに動かない(XPまででも制限ユーザでは使えない)というダメダメなアプリの一丁上がりです。個人的には、アプリと同じフォルダに設定ファイルを置くのはインストーラ無しのフリーソフトの特権だと思っています。長々とした文章ですみませんでした。
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 | #console
Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" (
lpAppName As *Byte,
pKeyName As *Byte,
lpString As *Byte,
lpFileName As *Byte) As BOOL
Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (
lpAppName As *Byte,
lpKeyName As *Byte,
lpDefault As *Byte,
lpReturnedString As *Byte,
nSize As DWord,
lpFileName As *Byte) As DWord
' PathGetArgsの利用にはIE4以上またはWindows 98/2000以上が必要。
Declare Function PathGetArgs Lib "shlwapi" Alias "PathGetArgsA" (pszPath As *Byte) As *Byte
Const BUF_SIZE = 1024
Dim lastCmdLine As String
lastCmdLine = ZeroString(BUF_SIZE)
GetPrivateProfileString("option", "LastCommandLineArgs", "(none)", StrPtr(lastCmdLine), BUF_SIZE , "H:\MYAPP.INI")
' "(none)"はファイル自体や中のエントリが見付からなかったときにlastCmdLineに格納する内容を指定する引数
Print "Last command line:"; lastCmdLine
Dim cmdLine As BytePtr
' PathGetArgsでコマンドライン引数から自身の実行ファイル名(Cでいうargv[0])の部分を取り除いている。
cmdLine = PathGetArgs(GetCommandLine())
WritePrivateProfileString("option", "LastCommandLineArgs", cmdLine, "H:\MYAPP.INI")
|
ああorz、投稿と間違えました。ごめんなさい。
設定ファイルを読み込むお題であれば過去に出ていますが、それとは違くて?
バッチファイルでレジストリの値を取得するコードを書きました。reg.exe呼んでるだけですが。
see: Preferences API 入門
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | ===== getreg.bat =====
@echo off
rem reg.exeの結果を1行ごと%rに格納する
for /F "usebackq delims=" %%r in (`reg.exe QUERY %1 /v %2`) do (
rem %rをタブ区切りデータとみなし、3列目を%tに格納する
for /F "tokens=3 delims= " %%t in ("%%r%") do (
rem %tが空でなければ、レジストリ値だとみなす
if not "%%t%" == "" (
echo %%t%
goto e
)
)
)
:e
===== 使用例 caller.bat =====
@echo off
for /F "usebackq delims=" %%v in (`call getreg "HKEY_CURRENT_USER\Control Panel\Desktop" Wallpaper`) do set WALLPAPER=%%v%
echo 壁紙=[%WALLPAPER%]
for /F "usebackq delims=" %%v in (`call getreg "HKEY_CURRENT_USER\Control Panel\Colors" ActiveTitle`) do set ACTIVETITLE=%%v%
echo タイトルバーの色=[%ACTIVETITLE%]
|
1 2 3 4 5 6 7 8 9 10 11 12 | import pickle
class Setting: pass
setting = Setting()
setting.message = 'Hello'
with open(r'.setting', 'w') as f:
pickle.dump(setting, f)
with open('.setting') as f:
s = pickle.load(f)
print s.message
|
Squeak Smalltalk で。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | "設定の作成(真偽値の場合)"
Preferences
addBooleanPreference: #myBoolPref
categories: #(unclassified)
default: false
balloonHelp: 'This is a sample boolean property.'
"設定値の変更(真偽値の場合)"
Preferences enable: #myBoolPref.
Preferences disable: #myBoolPref.
"現在の全設定の状態をファイルへ保存"
Preferences storePreferencesToDisk
"ファイルから全設定の状態を読み込み"
Preferences restorePreferencesFromDisk
|
お題のJavaを.NETに移植した感じ。 System.Configuration.dllを参照してビルドすること。
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | using System;
using System.Configuration;
class HelloPreference
{
const string MESSAGE_KEY = "message";
const string DEFAULT_MESSAGE = "Hello, Preference.";
public string Message { get; set; }
public Configuration Configuration { get; set; }
public HelloPreference()
{
LoadPreference();
}
public void LoadPreference()
{
Configuration conf = ConfigurationManager
.OpenExeConfiguration(ConfigurationUserLevel.None);
this.Configuration = conf;
KeyValueConfigurationElement element
= conf.AppSettings.Settings[MESSAGE_KEY];
this.Message = element != null
? element.Value
: DEFAULT_MESSAGE;
}
public void StorePreference()
{
Configuration conf = this.Configuration;
KeyValueConfigurationCollection settings
= conf.AppSettings.Settings;
KeyValueConfigurationElement elem
= settings[MESSAGE_KEY];
if (elem != null)
{
elem.Value = this.Message;
}
else
{
settings.Add(MESSAGE_KEY, this.Message);
}
conf.Save();
}
public void ShowMessage()
{
Console.WriteLine(this.Message);
}
static void Main(string[] args)
{
try
{
HelloPreference hello = new HelloPreference();
if (args.Length > 0)
{
hello.Message = args[0];
}
hello.ShowMessage();
hello.StorePreference();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
|
言語標準のやり方ということなので、Python標準添付のini書式設定ファイルのパーサを使った方法を示します。例とインターフェースを揃えるためにラッパを書いてますが、蛇足だったかも。
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 | import sys, os, ConfigParser
class HelloPreference:
path_cfg = os.path.join(os.path.expanduser('~'),
'org.doukaku.ja.preference.HelloPreference')
cfg = ConfigParser.ConfigParser()
def __init__(self):
self.cfg.read(self.path_cfg)
def __getattr__(self, attr):
if self.cfg.has_option('default', attr):
return self.cfg.get('default', attr)
else:
return None
def __setattr__(self, attr, value):
if not self.cfg.has_section('default'):
cfg.add_section('default')
self.cfg.set('default', attr, value)
def store(self):
f = file(self.path_cfg, 'w')
self.cfg.write(f)
f.close()
hello_prefs = HelloPreference()
if len(sys.argv) > 1:
hello_prefs.message = sys.argv[1]
print hello_prefs.message
hello_prefs.store()
|
すみません、ログインせずに書いたうえ、バグありでした。__setattr__の正しい実装はこうです。
1 2 3 4 | def __setattr__(self, attr, value):
if not self.cfg.has_section('default'):
self.cfg.add_section('default')
self.cfg.set('default', attr, value)
|
YAML形式の設定ファイルで。 設定をハッシュにして読み込み/保存しています。
1 2 3 4 5 6 7 8 9 10 | require 'yaml'
MESSAGE_KEY = 'message'
DEFAULT_MESSAGE = 'Hello, Preference.'
filename = 'conf.yaml'
conf = File.exist?(filename) ? YAML.load_file(filename) : { MESSAGE_KEY => DEFAULT_MESSAGE }
conf[MESSAGE_KEY] = ARGV[0] if ARGV.size > 0
p conf
open(filename, 'w') { |f| f.puts YAML.dump(conf) }
|
Groovy標準の設定ファイル形式ConfigSlurperでConfigObjectに読みこんでWriterに書き出してみます。
http://groovy.codehaus.org/gapi/groovy/util/ConfigObject.html http://groovy.codehaus.org/gapi/groovy/util/ConfigSlurper.html
正規化されて以下のような出力となります。 -- $ groovy config.groovy grails {
- webflow {
- stateless=true stateless2=true
}
} smtp {
- mail {
- host="smtp.myisp.com" auth.user="server"
}
} resources.URL="http://localhost:80/resources"
see: ConfigSlurper
1 2 3 4 5 6 7 8 9 10 11 12 13 | def config = '''
grails.webflow.stateless = true
grails.webflow.stateless2 = true
smtp {
mail.host = 'smtp.myisp.com'
mail.auth.user = 'server'
}
resources.URL = "http://localhost:80/resources"
'''
sw = new StringWriter()
new ConfigSlurper().parse(config).writeTo(sw)
println sw
|
(出し直し)
Groovy標準の設定ファイル形式ConfigSlurperでConfigObjectに読みこんでWriterに書き出してみます。
正規化されて以下のような出力となります。
$ groovy config.groovy
grails {
webflow {
stateless=true
stateless2=true
}
}
smtp {
mail {
host="smtp.myisp.com"
auth.user="server"
}
}
resources.URL="http://localhost:80/resources"
1 2 3 4 5 6 7 8 9 10 11 12 13 | def config = '''
grails.webflow.stateless = true
grails.webflow.stateless2 = true
smtp {
mail.host = 'smtp.myisp.com'
mail.auth.user = 'server'
}
resources.URL = "http://localhost:80/resources"
'''
sw = new StringWriter()
new ConfigSlurper().parse(config).writeTo(sw)
println sw
|





lunlumo #9190() [ Java ] Rating-2/4=-0.50
初期設定を読み書きするプログラムを書いてください。
保存先や形式は問いませんが,OS,ライブラリ,言語等の環境で標準的なものがあれば,なるべくそちらを用いてください。
Rating-2/4=-0.50-0+
[ reply ]