이전에 C#의 DataGridView에서 바로 Excel로 변환하는 글을 포스팅 한적 있습니다. 이번에는 실제 실무에서도 자주 쓰이는 CSV로 변환 하는 방법을 적어보겠습니다. CSV에서는 주로 콤마(,) 를 이용하여 컬럼을 구분하는데, 몇몇 특수한 경우 이를 무시해야할때가 있습니다. 예로 아이템 설명같은 문자열 부분 같은 경우죠. 그럴때에는 " 를 이용해서 그 부분을 감싸주어야 합니다.
( ex. "이 아이템은 캐릭터, 몬스터, 기타 NPC등이 사용합니다." )

또 한가지 염두해야 하는 것이 줄바꿈입니다. CSV 를 툴이나 Excel 등을 이용해 값을 작성하다보면 줄바꿈을 이용할때가 있는데,를 염두하지 않고, 파서를 만들면 전혀 엉뚱한 값을 읽을수 있게 됩니다. ( 줄바꿈을 아예 금지시키는것도 한 방법이기는 합니다 )

// DataGridView의 각행을 읽어 CSV로 변환
// pFileWrite가 CSV 파일 핸들
foreach (DataGridViewRow row in pDGV.Rows)
{
    bool bIsFirstValue = true;
    foreach (DataGridViewCell cell in row.Cells)
    {
        // 첫번째 셀 값이 없다면 이 행은 무시한다
        if (bIsFirstValue && null == cell.Value)
            break;

        if (!bIsFirstValue)
            pFilerWriter.Write(",");
        bIsFirstValue = false;

        // 빈값
        if (null == cell.Value)
            continue;

        // Cell 타입에 따라 값을 변환 ( ex. true/false -> 1/0 )
        // 기본적으로 Cell 값을 ""로 감싸 놓자
        switch (cell.Value.GetType().Name)
        {
            case "Boolean":
                {
                    String strTmp = (true == (bool)cell.Value) ? "1" : "0";
                    pFilerWriter.Write("\"" + strTmp + "\"");
                    break;
                }
            default:
                {
                    pFilerWriter.Write("\"" + cell.Value.ToString().Replace("\"", "\"\"") + "\"");
                    break;
                }
        }
    }
    pFilerWriter.WriteLine();
}


// CSV 파서
using ParsedColumn = List<string>;        // 컬럼 리스트
using ParsedRow = List<list<string>>;    // 로우 리스트
using (StreamReader pFilerReader = new StreamReader(strCSVFileName, Encoding.Default))
{
    ParsedColumn col = new ParsedColumn();
    bool bStartAppend = false;
    String strItem = "";
    String strCSV = pFilerReader.ReadToEnd();
    int iStrCSVLenth = strCSV.Length;
    for (int i = 0; i < iStrCSVLenth; ++i)
    {
        // "시작 이후 값들을 다 저장. 문자열을 완성한다.
        if (bStartAppend && '"' != strCSV[i])
        {
            strItem += strCSV[i];
            continue;
        }

        // " 시작. 이후 값들을 저장
        if (!bStartAppend && '"' == strCSV[i])
        {
            bStartAppend = true;
            continue;
        }

        // "가 끝났다.
        if (bStartAppend && '"' == strCSV[i])
        {
            bStartAppend = false;
            continue;
        }

        // 콤마가 나오면 조합된 문자열을 하나의 컬럼으로 저장.
        if (',' == strCSV[i])
        {
            col.Add(strItem);
            strItem = "";
            continue;
        }

        // 줄바꿈처리. ""로 감쌓여 있지 않은 상태에서 콤마 이후의 줄바꿈을 열의 끝을 의미한다.
        if('\r' == strCSV[i])
        {
            col.Add(strItem);
            strItem = "";
            m_ParsedRow.Add(col);
            ++i;            // \n을 건너뜀
            continue;
        }

        // 파일의 끝
        if ('\0' == strCSV[i])
        {
            col.Add(strItem);
            m_ParsedRow.Add(col);
            break;
        }

        strItem += strCSV[i];
    }
}

+ Recent posts