본문 바로가기
프로그래밍/C Sharp

[ C# ] ini 파일 읽기 및 쓰기 쉽게 쓸수 있는 클래스 공유

by jeong-f 2021. 11. 9.
반응형

C#에서는 환경 설정 파일로는 ini 파일을 사용하지 않고 app.config 파일을 다루지만
예전 C++과 MFC에서 사용하던 환경 설정에서 사용하던 편리함과  고객의 요구에 따라 사용해야 하는 경우가 있습니다.

커널 dll 호출 시 기본 함수 설명

GetPrivateProfileString() : 파일에서 정보(문자열) string형을 읽어옵니다.

GetPrivateProfileInt() : 파일에서 숫자형 int형을 읽어옵니다.

WritePrivateProfileString() : 파일에 정보(문자열) string형을 쓴다. 만약에 해당 섹션과 키값이 없으면 default값을 리턴합니다.

변수형 타입은 위의 string형, int형뿐만 아니라 숫자형 중 flot, double, int  및 bool 타입, rect 등 여러 가지 형태의 설정 형태로 응용이 필요한 경우가 있습니다.

이러한 자유로운 형식의 사용을 위하여 별도의 프로그램 구현을 통해 다각화된 변수형 지원 클래스를 만들어 배포하는데 목적이 있습니다.

ini 파일 다루기 클래스

사용자 클래스에는 위의 3가지 함수가 아니라 2가지의 함수를 외부로 사용할 수 있게 한 클래스를 구현할 것입니다.

여러 형식의 데이터를 읽고 쓸 수 있게 제작되어 유연하게 사용이 가능합니다.

GetPrivateProfile() : 파일에서 <T> 형 여러 가지 형의 데이터를 읽습니다.

GetPrivateProfile() : 파일에서 <T> 형 여러 가지 데이터를 읽습니다.

두 가지의 함수에서 여러 가지 변수형을 대응할 수 있어 좀 더 유연한 프로그램 코딩이 가능해집니다.

static class WinAPI
    {
        [DllImport("kernel32")]
        static extern bool WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName);

        [DllImport("kernel32")]
        public static extern int GetPrivateProfileInt(string lpAppName, string lpKeyName, int nDefault, string lpFileName);

        [DllImport("kernel32")]
        static extern int GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, int nSize, string lpFileName);

        // 추가 함수
        public static bool WritePrivateProfile(string _Section, string _Key, object _lpString, string _lpFileName)
        {
            _lpString = (_lpString == null) ? "" : _lpString;

            if (_lpString.GetType() == typeof(bool))
            {
                _lpString = ((bool)_lpString) ? "TRUE" : "FALSE";
            }
            else if (_lpString.GetType() == typeof(Rectangle))
            {
                Rectangle rect = (Rectangle)(object)_lpString;
                _lpString = string.Format("{0},{1},{2},{3}", rect.X, rect.Y, rect.Width, rect.Height);
            }
            else if (_lpString.GetType() == typeof(PointF))
            {
                PointF pf = (PointF)(object)_lpString;
                _lpString = string.Format("{0},{1}", pf.X, pf.Y);
            }
            else if (_lpString.GetType() == typeof(DateTime))
            {
                DateTime dt = (DateTime)(object)_lpString;
                _lpString = string.Format("{0:yyyy-MM-dd HH:mm:ss.fff}", dt);
            }

            return WritePrivateProfileString(_Section, _Key, _lpString.ToString(), _lpFileName);
        }
        public static T GetPrivateProfile<T>(string _Section, string _Key, T _lpDefault, string _lpFileName)
        {
            try
            {
                string defalut = "";

                if (typeof(T) == typeof(bool))
                {
                    defalut = (bool)(object)_lpDefault ? "TRUE" : "FALSE";
                }
                if (typeof(T) == typeof(DateTime))
                {
                    defalut = "";
                }
                else
                {
                    defalut = ((object)_lpDefault).ToString();
                }

                //------

                StringBuilder temp = new StringBuilder(512);
                int i = GetPrivateProfileString(_Section, _Key, defalut, temp, temp.Capacity, _lpFileName);

                if (typeof(T) == typeof(float))
                {
                    float fRev = 0;
                    float.TryParse(temp.ToString(), out fRev);
                    return (T)(object)fRev;
                }
                else if (typeof(T) == typeof(int))
                {
                    int nRev = 0;
                    int.TryParse(temp.ToString(), out nRev);
                    return (T)(object)nRev;
                }
                else if (typeof(T) == typeof(bool))
                {
                    return (T)(object)(temp.ToString().ToUpper() == "TRUE");
                }
                else if (typeof(T) == typeof(string))
                {
                    return (T)(object)(temp.ToString());
                }
                else if (typeof(T) == typeof(DateTime))
                {
                    DateTime dt = DateTime.MinValue;
                    string format = "yyyy-MM-dd HH:mm:ss.fff";
                    if (DateTime.TryParseExact(temp.ToString(), format, null, DateTimeStyles.AssumeLocal, out dt))
                    {
                    }

                    return (T)(object)(dt);
                }
                else if (typeof(T) == typeof(PointF))
                {
                    PointF pf = new PointF();

                    string[] split = temp.ToString().Split(',');

                    int x=0, y=0;
                    if (split.Length >= 2 && int.TryParse(split[0], out x) && int.TryParse(split[0], out y))
                    {
                        pf.X = x;
                        pf.Y = y;
                    }

                    return (T)(object)(pf);
                }
                else if (typeof(T) == typeof(Rectangle))
                {
                    Rectangle rect = new Rectangle();

                    string[] split = temp.ToString().Split(',');

                    int x = 0, y = 0, width=0,heigth=0;
                    if (split.Length >= 4 && 
                        int.TryParse(split[0], out x) && 
                        int.TryParse(split[1], out y) &&
                        int.TryParse(split[2], out width) &&
                        int.TryParse(split[3], out heigth))
                    {
                        rect.X = x;
                        rect.Y = y;
                        rect.Width = width;
                        rect.Height = heigth;
                    }

                    return (T)(object)(rect);
                }
                else
                {
                    return (T)(object)temp;
                }
            }
            catch (Exception)
            {
                return _lpDefault;
            }
        }
    }

함수 호출

int, double, float , bool, datetime, pointF, Rectangle을 지원하도록 제작되었습니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;

namespace IniFile
{
    class Program
    {
        static void Main(string[] args)
        {
            int nVal=100 ,nVal2;
            double dVal=101, dVal2;
            float  fVal= 102.1f , fVal2;
            bool bVal = true , bVal2;
            PointF pointf = new PointF(10,20), pointf2;
            Rectangle rect = new Rectangle(1,2,3,4) , rect2;
            DateTime dt = DateTime.Now, dt2;

            string fileName = Application.StartupPath  + "\\test.ini";

            // ini파일 쓰기
            WinAPI.WritePrivateProfile("Main", "int", nVal, fileName);
            WinAPI.WritePrivateProfile("Main", "double", dVal, fileName);
            WinAPI.WritePrivateProfile("Main", "float", fVal, fileName);
            WinAPI.WritePrivateProfile("Main", "bool", bVal, fileName);
            WinAPI.WritePrivateProfile("Main", "PointF", pointf, fileName);
            WinAPI.WritePrivateProfile("Main", "Rectangle", rect, fileName);
            WinAPI.WritePrivateProfile("Main", "DateTime", dt, fileName);

            Console.WriteLine("** Write **");
            Console.WriteLine("int={0}", nVal);
            Console.WriteLine("double={0}", dVal);
            Console.WriteLine("float={0}", fVal);
            Console.WriteLine("bool={0}", bVal);
            Console.WriteLine("PointF={0}", pointf);
            Console.WriteLine("Rectangle={0}", rect);
            Console.WriteLine("DateTime={0}", dt);

            // ini파일 읽기
            nVal2= WinAPI.GetPrivateProfile("Main", "int",0, fileName);
            dVal2= WinAPI.GetPrivateProfile("Main", "double", 0, fileName);
            fVal2 =WinAPI.GetPrivateProfile("Main", "float", 0f, fileName);
            bVal2 = WinAPI.GetPrivateProfile("Main", "bool", false, fileName);
            pointf2 = WinAPI.GetPrivateProfile("Main", "PointF", PointF.Empty, fileName);
            rect2 = WinAPI.GetPrivateProfile("Main", "Rectangle", Rectangle.Empty, fileName);
            dt2 = WinAPI.GetPrivateProfile("Main", "DateTime", DateTime.Now, fileName);

            Console.WriteLine();
            Console.WriteLine("** Read **");
            Console.WriteLine("int={0}", nVal2);
            Console.WriteLine("double={0}", dVal2);
            Console.WriteLine("float={0}", fVal2);
            Console.WriteLine("bool={0}", bVal2);
            Console.WriteLine("PointF={0}", pointf2);
            Console.WriteLine("Rectangle={0}", rect2);
            Console.WriteLine("DateTime={0}", dt2);

            Console.Read();
        }
    }
}

실행 결과

쓰는 데이터와 읽은 데이터가 같은 것을 확인할 수 있습니다.

ini파일은 자동으로 생성되었고, 변수형에 맞는 형식으로 저장되었습니다.

반응형

댓글