사용자의 설정을 기억할 목적으로 ini파일을 사용해 보고자 만들었다.
INI파일을 로드하고, 원하는 항목을 return 하는 기능을 구현했다.
일부러 이번엔 다른 사람의 코드를 먼저 보지않고, 내 나름대로 작성한 후에 봤다.
작성 후, 다른 사람의 소스를 보니 굉장히 간결했다. 아직 가야할 길이 먼 것 같다.
(비교: http://www.codeproject.com/Articles/1966/An-INI-file-handling-class-using-C)
검색된 소스는 GetPrivateProfileString, WritePrivateProfileString라는 API를 사용했다.
using System.Collections.Generic; using System.Collections; using System.IO; using System.Diagnostics; namespace automating_system_report { #region INISTRUCT public class INISTRUCT //INI파일의 한 줄의 내용을 저장할 class. List로 사용함. { public string lvar; // 왼쪽 문자열(상수이름) public string rvar; // 오른쪽 문자열(상수값) public INISTRUCT(string inputLvar, string inputRvar) { lvar = inputLvar; rvar = inputRvar; } } #endregion #region INILoader ////// INI 파일을 읽어 , 데이터 이름과 데이터 값을 listINI 리스트에 저장하는 클래스. /// INILoader를 선언하고, LoadINIFile("filename") 메쏘드를 실행하면, /// INI파일의 값들을 클래스 내의 listINI 리스트에 저장한다. /// public class INILoader { #region globar var private string matchString; //Predicate함수로 전달할 목적으로 전역 변수를 사용함. #endregion #region public member //INISTRUCT의 List public ListlistINI = new List (); #endregion #region public method // INI파일을 로딩, public bool LoadINIFile(string filename) { try { if (File.Exists(filename)) { FileStream fs = File.OpenRead(filename); StreamReader sr = new StreamReader(fs); while (sr.Peek() > -1) // Peek은 문자가 더 이상 없으면 반환 값은 -1 이다. { FillINISTRUCT(sr.ReadLine()); // FillINIStruct로 전역 리스트 listINI에 값을 저장함. } sr.Close(); fs.Close(); return true; } return false; } catch { return false; } } public void SaveINIFile(string filename) { try { /* FileStream fs=new FileStream(filename); * StreamWriter sw=new StreamWriter(fs); * 이렇게 해서 쓰면, 생성된 파일 끝부분에 이전의 쓰레기 값이 남았다...왜 그런지는 알아봐야함. * 이미 있는 파일에 덮어쓰기 할 때, 이전 값이 더 클 경우 쓰레기 값이 남는 것으로 보임. */ StreamWriter sw = new StreamWriter(filename,false, System.Text.Encoding.Unicode); foreach (INISTRUCT i in listINI) { sw.WriteLine(@i.lvar + " = " + @i.rvar); //Trace.WriteLine("sw:"+i.lvar + "," + i.rvar); } sw.Close(); } catch { } } public bool AddINI(string inistr) { INISTRUCT inputINI = StringToINISTRUCT(inistr); for (int i = 0; i < listINI.Count; i++) { if (listINI[i].lvar == inputINI.lvar) //이미 해당 lvar가 있으면 rvar를 수정 { Trace.WriteLine(listINI[i].rvar+"->"+inputINI.rvar); listINI[i].rvar = inputINI.rvar; return true; } } listINI.Add(inputINI); // 기존에 없던 rvar값이면 추가. return true; } public string FindValue(string valueName) { //valueName의 lvar를 찾아 rvar를 return matchString = valueName; try { INISTRUCT pickINI = listINI.Find(MatchingPredicate); // MatchingPredicate의 주석 참조. return pickINI.rvar; //"valueName = matchString = 찾고자 하는 lvar의 이름"으로 찾은 rvar의 값 } catch { return null; // lvar에 valueName없음. } } #endregion #region private method private bool MatchingPredicate(INISTRUCT p) { /// http://msdn.microsoft.com/ko-kr/library/x0b5b5bc.aspx /// MSDN에서는 Predicate 함수를 static으로 선언하고 있어, matchString도 static으로 선언해야 한다... /// Predicate함수와 matchString을 둘 다 static에서 해제 했음. /// 람다식을 이용하면 더 깔끔한(전역변수 남용 없이, predicate 선언 없이..) 구현할 수 있을 것 같다. return (matchString == p.lvar); } /// /// INI파일에서 읽어들인 레코드를 Substring, Trim 하는 함수 /// /// "상수이름 = 값" 형식의 문자열 private void FillINISTRUCT(string tmpiniString) { //Trim된 Rvar와 Lvar를 리스트에 Add() INISTRUCT tmpinistruct = StringToINISTRUCT(tmpiniString); listINI.Add(tmpinistruct); } public INISTRUCT StringToINISTRUCT(string inistr) { int locateEqualMark; // "=" 마크 위치 int locateRvarStart, locateRvarEnd; // rvar substring 위치 string tmpLvar; // lvar를 저장할 임시 변수 string tmpRvar; // rvar를 저장할 임시 변수 //substring 할 위치 locateEqualMark = inistr.IndexOf('='); locateRvarStart = locateEqualMark + 1; locateRvarEnd = inistr.Length - locateEqualMark - 1; //substring if (locateEqualMark == -1) {return null;} // Trim하기 전의 임시변수 tmpLvar = inistr.Substring(0, locateEqualMark); tmpRvar = inistr.Substring(locateRvarStart, locateRvarEnd); //앞뒤 공백제거 " some string" or "some string " => "some string" tmpLvar = tmpLvar.Trim(); tmpRvar = tmpRvar.Trim(); return new INISTRUCT(tmpLvar, tmpRvar); } #endregion } #endregion } //
테스트 코드
#region global var INILoader ini = new INILoader(); #endregion #region const var public const string inifilename = @"C:\windows\win.ini"; #endregion public DlgOption() { InitializeComponent(); ini.LoadINIFile(inifilename); //테스트 foreach foreach (INISTRUCT s in ini.listINI) { string traceString; traceString=string.Format("Trace: \"{0}\", \"{1}\"",s.lvar,s.rvar); Trace.WriteLine(traceString); } Trace.WriteLine("find="+ini.FindValue("mp3")); Trace.WriteLine("find=" + ini.FindValue("MP3")); } /* 테스트 Trace: "CMC", "1" Trace: "MAPI", "1" Trace: "MAPIX", "1" Trace: "MAPIXVER", "1.0.0.1" Trace: "OLEMessaging", "1" find=MPEGVideo <- "MP3" 검색결과 'System.NullReferenceException' 형식의 첫째 예외가 automating_system_report.exe에서 발생했습니다. find= <- 찾는 항목 없음 "mp3" 검색결과... */ //
댓글 없음:
댓글 쓰기