[C#] 하위 폴더 내부의 파일 목록 얻는 함수

특정 폴더에 대해서 그 하위 폴더까지 확장자가 .shp 인 파일 목록을 얻어는 함수입니다. 확장자의 지정은 함수 내부에 마법의 상수값으로 박혀 있습니다.

private void GetShpFileNames(string folderName, ArrayList fileNamesList)
{
    System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(folderName);
    foreach (System.IO.FileInfo f in di.GetFiles())
    {
        if (f.Extension.ToLower().CompareTo(".shp") == 0)
        {
            String strInFileName = di.FullName + "\\" + f.Name;
            fileNamesList.Add(strInFileName);
        }
    }

    foreach (System.IO.DirectoryInfo sd in di.GetDirectories())
    {
        GetShpFileNames(sd.FullName, fileNamesList);
    }
}

최근에 C# 5.0에 대한 책을 3일에 걸쳐 대충 설렁 설렁 봤더랬습니다. 비록 위의 코드는 C#의 고전 문법만 존재하지만.. 여하튼, 클라이언트 단의 개발 언어로써 C#은 정말 단연 최고가 아닌가 할 정도였습니다. 자바스크립트의 비슷한 개념도 가져오고, 특히나 클래스 타입 자체를 동적으로 생성하는 기능에서는 ‘미친거아냐?’라는 생각마저 들었습니다. 마치 프로그램이 프로그램을 만들 수 있다라는 개념도 가능하다는 것이죠. 이런 미친…. -_-;

[C#] 지정된 폴더(Folder)에서 파일명(File Name) 목록(List) 얻기

C#에서 지정된 폴더에 담긴 파일명의 목록을 얻는 코드입니다.

String FolderName = tbFolder.Text;
System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(FolderName);
foreach (System.IO.FileInfo File in di.GetFiles())
{
    if (File.Extension.ToLower().CompareTo(".xrv") == 0)
    {
        String FileNameOnly = File.Name.Substring(0, File.Name.Length - 4);
        String FullFileName = File.FullName;

        MessageBox.Show(FullFileName + " " + FileNameOnly);
    }
}

1번 코드에서 파일명 목록을 얻고자 하는 폴더명이 지정됩니다. 그리고 5번에서 확장자가 .xrv 인 파일만을 필터링합니다. 그리고 7번은 오직 파일명(경로와 확장자를 제외)만을 얻습니다. 끝으로 8번은 파일명의 전체 이름(경로와 확장자를 포함)을 얻습니다.

폴더 안의 서브 폴더를 처리하기 위해서는 DirectoryInfo의 GetDirectories 매서드를 사용하여 서브 폴더명의 리스트를 얻어와 처리하면 됩니다.

CSV 포맷(Format)의 문자열(String) 파싱(Parse, Parsing)

CSV 형태로 된 문자열을 파싱하기 위한 C#언어로 작성된 함수입니다. 예전에 XrGeocoder 프로그램을 개발할때 사용했던 함수로.. 또 다른 프로젝트에서 사용되면서 함수만을 분리해 정리해 봅니다.>/p>

private List SeperateStringWithComma(String value)
{
    bool inQuotes = false;
    char delim = ',';
    List strings = new List();

    StringBuilder sb = new StringBuilder();
    foreach (char c in value)
    {
        if (c == '\'' || c == '"')
        {
            if (!inQuotes)
                inQuotes = true;
            else
                inQuotes = false;
        }

        if (c == delim)
        {
            if (!inQuotes)
            {
                strings.Add(sb.Replace("'", string.Empty).Replace("\"", string.Empty).ToString());
                sb.Remove(0, sb.Length);
            }
            else
            {
                sb.Append(c);
            }
        }
        else
        {
            sb.Append(c);
        }
    }

    strings.Add(sb.Replace("'", string.Empty).Replace("\"", string.Empty).ToString());
    return strings;
}

위의 함수를 사용하는 예제는 다음과 같습니다.

String csv = "2011-01-01,18,2008,개인,인천,중구,~,2010-12-31,233400,남자";
List values = SeperateStringWithComma(csv);

int cntValues = values.Count;
for (int i = 0; i < cntValues; i++)
{
    MessageBox.Show(values[i]);
}

C#의 스레드(Thread)에서 UI 컨트롤 사용하기

기본적으로 UI를 갖는 컨트롤은 메인 스레드가 아닌 다른 스레드에서 접근될때 충돌(Crash)이 발생합니다. 현재 C/S 기반의 맵엔진인 듀라맵을 서버단에서 사용하고 있으며, 서버에서 여러 개의 스레드에서 UI 컨트롤인 듀라맵에 접근할때 아래와 같은 충돌이 발생합니다.

사용자 삽입 이미지

이에 대한 해결 방안은 델리게이트(Delegate)와 UI 컨트롤을 담는 Form 클래스의 Invoke 매서드를 사용해 해결할 수 있습니다.

예를 들어서 지도 엔진인 듀라맵을 이용해 어떤 지점이 특정 폴리곤에 포함(Contain)하는지에 대한 기능을 수행하고자 할 때를 살펴 보겠습니다.

듀라맵을 이용해 다음과 같은 Contain이라는 새로운 사용자 정의 매서드를 만들었습니다. 이 Contain 매서드의 위치는 어디라도 상관이 없습니다. 중요한 것은, 바로 이 Contain이라는 매서드가 별도의 스레드를 통해 호출된다는 것이고 델리게이트 기법을 사용하지 않는다면 충돌이 발생합니다.

public bool Contain(double X, double Y, int FID)
{
    //UI 컨트롤 사용
}

별도의 스레드에서 문제 없이 위에서 언급한 Contain이라는  매서드를 호출하기 위해서는, Contain 매서드를 직접 호출하지 않고 델리게이트(대리자)를 사용하면 됩니다. 델리게이트를 다음처럼 Contain 매서드가 존재하는 같은 클래스에 선언합니다.

private delegate bool DelegateContain(double X, double Y, int FID);
private DelegateContain delegateContain;

이제 위의 델리게이트와 Contain 매서드를 연결하는 코드는 다음과 같습니다.

delegateContain = new DelegateContain(Contain);

이제 메인 스레드가 아닌 스레드에서 Contain 매서드의 기능을 활용하기 위해서는 Contain에 대한 델리게이트인 delegateContain를 사용하면 됩니다. 즉, 다음처럼…

bool bContain = (bool)form.Invoke(delegateContain, X, Y, FID);

스레드에서 사용하고자 하는 UI 컨트롤이 담긴 폼 객체의 Invoke 매서드를 사용해 delegateContain을 호출하며 Contain 매서드의 인자는 Invoke 매서드를 통해 전달하면 됩니다. Invoke는 가변 인자를 받으므로 인자의 제약이 덜합니다. 또한 Invoke의 반환값은 델리게이트 대상이 되는 함수의 반환값이며 object 타입이므로 Contain 매서드의 반환값으로 형변환하여 사용하면 됩니다.