사용자의 설정을 기억할 목적으로 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 List listINI = 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" 검색결과...
*/
//
댓글 없음:
댓글 쓰기