낭만 프로그래머

C#에서 CSV 파일 읽기 본문

C#

C#에서 CSV 파일 읽기

조영래 2020. 9. 12. 20:59

C#에서 CSV 파일을 읽어오는 방법은 다양하다. 이번엔 Microsoft.VisualBasic.FileIO를 사용하여 읽어오는 방법을 소개 한다.

* 기본적으로 Excel에서 작성후 CSV로 저장시에 항상 UTF-8 형태로 저장해야 한다. 


#소스

/// <summary>
/// CSV 파일을 읽기
/// </summary>
/// <param name="filePath">CSV 파일 경로</param>
/// <param name="isFirstHeader">첫번째 행의 헤더여부</param>
/// <param name="commentTokens">주석처리 문자열</param>
/// <param name="delimiter">구분자 문자열</param>
/// <param name="hasEnclosedInQutes"></param>
/// <returns></returns>
public static Dictionary<String, List<String[]>> readCSV(String filePath, bool isFirstHeader, String commentTokens, String delimiter, bool hasEnclosedInQutes)
{
    Dictionary<String, List<String[]>> returnvalue = new Dictionary<String, List<String[]>>();
    List<String[]> headerList = new List<String[]>();
    List<String[]> dataList = new List<String[]>();
    returnvalue.Add("Header", headerList);
    returnvalue.Add("Data", dataList);

    try
    {
        using (TextFieldParser csvReader = new TextFieldParser(filePath))
        {
            csvReader.CommentTokens = new string[] { commentTokens };
            csvReader.SetDelimiters(new string[] { delimiter });
            csvReader.HasFieldsEnclosedInQuotes = hasEnclosedInQutes;

            int count = 0;
            while (!csvReader.EndOfData)
            {
                // Read current line fields, pointer moves to the next line.
                String[] fields = csvReader.ReadFields();

                if (isFirstHeader && count == 0) // 첫번째 줄이 Header 일 경우
                {
                    headerList.Add(fields);
                }
                else
                {
                    dataList.Add(fields);
                }
                
                count++;
            }

        }
    }
    catch(Exception e)
    {
        Console.WriteLine(e.StackTrace);
    }

    return returnvalue;
}


/// <summary>
/// Header를 가지고 있는 CSV를 읽어서 Dictionary의 List로 반환
/// </summary>
/// <param name="filePath">CSV 파일 경로</param>
/// <param name="commentTokens">주석처리 문자열</param>
/// <param name="delimiter">구분자 문자열</param>
/// <param name="hasEnclosedInQutes"></param>
/// <returns></returns>
public static List<Dictionary<String, String>> readCSVWithHeader(String filePath, String commentTokens, String delimiter, bool hasEnclosedInQutes)
{
    List<Dictionary<String, String>> returnvalue = new List<Dictionary<String, String>>();

    try
    {
        using (TextFieldParser csvReader = new TextFieldParser(filePath))
        {
            csvReader.CommentTokens = new string[] { commentTokens };
            csvReader.SetDelimiters(new string[] { delimiter });
            csvReader.HasFieldsEnclosedInQuotes = hasEnclosedInQutes;

            String[] headers = null;
            bool isFirst = true;
            while (!csvReader.EndOfData)
            {
                // Read current line fields, pointer moves to the next line.
                String[] fields = csvReader.ReadFields();

                if (isFirst) // 첫번째 줄이 Header
                {
                    headers = fields;
                    isFirst = false;
                }
                else
                {
                    Dictionary<String, String> dataDic = new Dictionary<String, String>();
                    returnvalue.Add(dataDic);

                    for (int i=0; i<fields.Length; i++)
                    {
                        dataDic.Add(headers[i], fields[i]);
                    }
                }
            }

        }
    }
    catch (Exception e)
    {
        Console.WriteLine(e.StackTrace);
    }

    return returnvalue;
}