初期化ファイルを読み取るWindowsアプリケーション
- 2019年9月18日
- Windows
前回に引き続き、勉強を兼ねたC#を使ったWindows用コンソールアプリケーションです。
初期化ファイル(.ini) から設定を読み取ってそれを元にコンソールに表示を行います。

[DllInport(“KERNEL32.DLL”)]から始まる箇所はWin32 APIを使用し、
初期化ファイルから値を読み取るための宣言です。
その他定数の定義や、読み取った設定を格納するための構造体を
宣言しています。
// Win32APIの GetPrivateProfile~~ を使う宣言
// string取得用
[DllImport("KERNEL32.DLL")]
public static extern uint
GetPrivateProfileString(string lpAppName,
string lpKeyName, string lpDefault,
StringBuilder lpReturnedString, uint nSize,
string lpFileName);
// int取得用
[DllImport("KERNEL32.DLL")]
public static extern uint
GetPrivateProfileInt(string lpAppName,
string lpKeyName, int nDefault,
string lpFileName);
// 読み込む設定のセクション名
private static readonly string GENERAL_SECTION = ("General");
// 設定のキーと初期値(内容は省略しています)
private struct GENERAL
{
public struct OUTPUT_DIRECTRY
public struct BIRTH_YEAR
public struct BIRTH_MONTH
public struct BIRTH_DAY
public struct RANGE_MIN
public struct RANGE_MAX
public struct ITEM_NUM
}
// 設定ファイル名
private static readonly string SETTING_FILE_PATH = ("setting.ini");
private static readonly string CURRENT_DIRECTORY = (AppDomain.CurrentDomain.BaseDirectory);
// 読み取った設定を格納する構造体
private struct GeneralSetting
{
public string output_directry;
public int birth_year;
public int birth_month;
public int birth_day;
public int range_min;
public int range_max;
public int item_num;
}
初期化ファイルを読み込んでる関数群です。
Win32APIの関数を使用して取得したデータを構造体へ保存しています。
/**
* 設定読み取り関数
* Generalセクションの設定を読み取って構造体のメンバに代入し返します。
*
*/
private static GeneralSetting loadGeneralSetting()
{
string section = (GENERAL_SECTION);
GeneralSetting ret;
ret.output_directry = loadStringVal(section, GENERAL.OUTPUT_DIRECTRY.KEY, GENERAL.OUTPUT_DIRECTRY.DEFAULT_VAL);
ret.birth_year = loadIntVal(section, GENERAL.BIRTH_YEAR.KEY, GENERAL.BIRTH_YEAR.DEFAULT_VAL);
ret.birth_month = loadIntVal(section, GENERAL.BIRTH_MONTH.KEY, GENERAL.BIRTH_MONTH.DEFAULT_VAL);
ret.birth_day = loadIntVal(section, GENERAL.BIRTH_DAY.KEY, GENERAL.BIRTH_DAY.DEFAULT_VAL);
ret.range_min = loadIntVal(section, GENERAL.RANGE_MIN.KEY, GENERAL.RANGE_MIN.DEFAULT_VAL);
ret.range_max = loadIntVal(section, GENERAL.RANGE_MAX.KEY, GENERAL.RANGE_MAX.DEFAULT_VAL);
ret.item_num = loadIntVal(section, GENERAL.ITEM_NUM.KEY, GENERAL.ITEM_NUM.DEFAULT_VAL);
return ret;
}
/**
* 指定セクションの指定キーの値をstringとして読み取る関数
*
*/
private static string loadStringVal(string section, string key, string defVal)
{
StringBuilder sb = new StringBuilder(1024);
GetPrivateProfileString(
section, // セクション名
key, // キー名
defVal, // 値が取得できなかった場合に返される初期値
sb, // 格納先
Convert.ToUInt32(sb.Capacity), // 格納先のキャパ
CURRENT_DIRECTORY + SETTING_FILE_PATH
); // iniファイル名
return sb.ToString();
}
/**
* 指定セクションの指定キーの値をintとして読み取る関数
*
*/
private static int loadIntVal(string section, string key, int defVal)
{
return (int)GetPrivateProfileInt(section, key, defVal, CURRENT_DIRECTORY + SETTING_FILE_PATH);
}
/**
* 指定ファイルを指定エンコードで読み取って一行ずつコンソールに出力する関数
*
*/
private static string readSetting(string filePath, string encoding)
{
if (!File.Exists(filePath))
{
return "";
}
System.Text.Encoding enc = System.Text.Encoding.GetEncoding(encoding);
string[] readText = File.ReadAllLines(filePath, enc).ToArray();
return String.Join("\n", readText);
}
メイン関数です。
初期化ファイルの設定を元に指定範囲内の乱数値を指定個数表示する簡単なプログラムです。
static void Main(string[] args)
{
Console.WriteLine(SETTING_FILE_PATH);//初期化ファイル名
Console.WriteLine(readSetting(SETTING_FILE_PATH, "shift_jis"));//初期化ファイルの内容
Console.WriteLine("");//空白行
Console.WriteLine("上記の設定を元に乱数を表示します。");
// 設定読取
GeneralSetting generalSetting = loadGeneralSetting();
// 読み取った生年月日をDateTime型に
var birthDate = DateTime.Parse(String.Format("{0}/{1}/{2}", generalSetting.birth_year, generalSetting.birth_month, generalSetting.birth_day));
// 現在時間+生年月日をシードに乱数
var rnd = new System.Random(((int)(DateTime.Now.Ticks + birthDate.Ticks) & 0x0000ffff));
StringBuilder sb = new StringBuilder(256);
sb.Clear();
sb.Append("出力結果 : ");
// 設定ファイルから読み取った回数分ループを実行
for (int i = 0; i < generalSetting.item_num; i++)
{
// 設定ファイルから読み取った下限値~上限値の範囲で乱数を文字列結合
sb.Append(rnd.Next(generalSetting.range_min, generalSetting.range_max+1));
sb.Append(" ");
}
Console.WriteLine(sb.ToString().Trim());
return;
}
これを作成した理由ですが、数字をいくつか選ぶタイプの宝くじで数字をパパっと決めたい時に便利かなと思い作成しました。
C#はC言語要素のあるJavaみたいな印象ですね。型推論があって便利です。
水曜担当:Tanaka
tanaka at 2019年09月18日 10:00:47