ファイル」タグアーカイブ

C# で ini ファイルの内容を任意のクラスに格納するコードを書いてみた。

どうもみむらです。

C# で ini ファイルを操作するとなると、
よくあるのが GetPrivateProfileString あたりを叩いて取得することになります。

でもその場合、いちいち要素を指定して取得しなければならず、
特に複数のキー(フィールド)がある場合に複数回コードを書くのも面倒です。

特に ini ファイルの項目が多くて、こんな状態になった日には・・。

image

 

・・ということで、 Reflection を使用して
この辺をすごく楽に出来るような感じでコードを書いてみました。

 

コード:

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

public static class Ini
{
    [DllImport("KERNEL32.DLL")]
    public static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, uint nSize, string lpFileName);

    [DllImport("KERNEL32.DLL")]
    public static extern uint GetPrivateProfileInt(string lpAppName, string lpKeyName, int nDefault, string lpFileName);

    [DllImport("KERNEL32.DLL")]
    public static extern uint WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName);

    public static T Read<T>(string section, string filepath)
    {
        T ret = (T)Activator.CreateInstance(typeof(T));

        foreach (var n in typeof(T).GetFields())
        {
            if (n.FieldType == typeof(int))
            {
                n.SetValue(ret, (int)GetPrivateProfileInt(section, n.Name, 0, Path.GetFullPath(filepath)));
            }
            else if (n.FieldType == typeof(uint))
            {
                n.SetValue(ret, GetPrivateProfileInt(section, n.Name, 0, Path.GetFullPath(filepath)));
            }
            else
            {
                var sb = new StringBuilder(1024);
                GetPrivateProfileString(section, n.Name, "", sb, (uint)sb.Capacity, Path.GetFullPath(filepath));
                n.SetValue(ret, sb.ToString());
            }
        };

        return ret;
    }

    public static void Write<T>(string secion, T data, string filepath)
    {
        foreach (var n in typeof(T).GetFields())
        {
            WritePrivateProfileString(secion, n.Name, n.GetValue(data).ToString(), Path.GetFullPath(filepath));
        };
    }
}

 

使い方:

ini ファイルの読み取りたいセクションに合わせたクラスを用意します。

    public class Human
    {
        public string name;
        public int age;
    }

でもって次のような ini ファイルを用意して

[01]
name=TARO
age=20

あとはこんな風に呼び出します。

        static void Main(string[] args)
        {
            var h = Ini.Read<Human>("01", "DATA.INI");

            h.age = 15;
            h.name = "JIRO";
            Ini.Write("02", h, "DATA.INI");
        }

 

実行しますと、

image

こんな感じでデータが読み出されます。

でもって、 ini ファイルは

[01]
name=TARO
age=20
[02]
name=JIRO
age=15

こんな感じに、ちゃんとセクション 02 が書き込まれます。


躓きそうなところ:

データを格納するクラスが、こういう感じに {get; set;} な状態になっている場合:

    public class Human
    {
        public string name { get; set; }
        public int age { get; set; }
    }

上記コード内の GetFields を GetProperties に換え、 FieldType を PropertyType に変えれば動作します。


・・そんなわけで、もし良ければ自己責任でご利用ください-。

Hyper-V で ディスクの最適化をしても VHDX ファイルが縮まらない場合。

みむらです。何となくメモ。

image

Hyper-V において、こんな感じで仮想ハードディスクに対して最適化を行っても縮まらない場合。

 

1. 事前にゲストOS 上で 空き領域を 0-fill しておく。

2. PowerShell を起動して、 Users\Public\Documents\Hyper-V\Virtual hard disks に移動。

image

3. “Optimize-VHD [縮めたい vhdxファイル] –Mode Prezeroed” を実行。

image

ということで、終われば縮まります。