CSV를 활용한 데이터 저장 및 불러오기

Youngmin Go·2024년 9월 14일
0
post-thumbnail
post-custom-banner

유니티 시스템 프로그래밍이라는 인프런의 강의를 보고 학습하는 내용을 정리하고 기록하는 글입니다.

Unity 시스템 프로그래밍 학습 기록 - 섹션 4-2
이번 섹션 4-2에서는 CSV형식으로 데이터를 저장하고 불러오는 방법에 대해 공부했습니다.

기존 프로젝트에서는 JSON 형식의 데이터를 관리해본 적은 있지만, CSV 형식의 데이터를 다룬 경험은 없었습니다. 이번 학습을 통해 CSV 형식의 데이터 관리 방법을 익힐 수 있어 향후 프로젝트에 활용할 수 있는 기회를 얻었습니다.

CSV란?

CSV는 Comma-Separated Values의 약자로, 데이터를 쉼표로 구분하여 저장하는 파일 형식입니다. CSV 파일은 주로 데이터의 간단한 저장 및 전송에 사용됩니다.

다음은 CSV 형식의 파일 예시입니다:

이름,나이,직업
홍길동,25,프로그래머
김철수,30,디자이너
이영희,22,마케터

CSV의 장점

CSV 형식의 주요 장점은 다음과 같습니다:

간결하고 직관적: CSV 파일은 사람이 쉽게 읽고 이해할 수 있도록 설계되어 있습니다. 각 행은 레코드를 나타내고, 각 열은 속성을 나타내기 때문에 데이터 구조가 명확합니다.
높은 호환성: CSV는 엑셀, 구글 스프레드시트 등 다양한 프로그램에서 지원되므로, 데이터 전송 및 공유가 용이합니다.
효율적인 저장 공간: 구조가 단순하여 메모리와 저장 공간을 적게 사용합니다. 대량의 데이터를 다룰 때도 유리합니다.

CSV 파싱

CSV 형식의 데이터를 파싱하여 구조화된 정보로 변환하는 과정을 CSV 파싱이라고 합니다. 예를 들어 위에 있는 데이터를 파싱하면 아래와 같이 변환 할 수 있습니다.

이름: 홍길동
나이: 25
직업: 프로그래머

Unity에서의 CSV 처리

Unity에서는 JSON 형식을 기본적으로 지원하지만, CSV 형식은 지원하지 않습니다. 따라서 외부 라이브러리인 CSVHelper를 사용하여 CSV 데이터를 간편하게 파싱할 수 있습니다. 이 라이브러리는 사용이 쉽고, 강력한 기능을 제공하므로 CSV 파일을 다루는 데 매우 유용합니다.

아래 코드는 CSVHelper의 코드입니다.

public class CSVHelper<T> where T : class, new()
{
    private static readonly char Separator = ',';
    private static readonly char Quote = '"';

    public static List<T> Read(string fileName)
    {
        List<T> list = new List<T>();

        TextAsset csv = Resources.Load<TextAsset>(fileName); // Resources 폴더에서 파일 읽기
        if (csv == null)
        {
            Debug.LogError("File not found: " + fileName);
            return list;
        }

        string[] lines = csv.text.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
        if (lines.Length == 0)
        {
            Debug.LogWarning("CSV file is empty.");
            return list;
        }

        // CSV 헤더를 읽어 필드 이름을 추출
        string[] headers = lines[0].Split(Separator);
        
        for (int i = 1; i < lines.Length; i++)
        {
            string[] values = lines[i].Split(Separator);
            if (values.Length != headers.Length) continue;

            T obj = new T();
            for (int j = 0; j < headers.Length; j++)
            {
                var property = typeof(T).GetProperty(headers[j]);
                if (property != null)
                {
                    object value = Convert.ChangeType(values[j].Trim(Quote), property.PropertyType);
                    property.SetValue(obj, value);
                }
            }
            list.Add(obj);
        }
        return list;
    }

    public static void Save(string filePath, List<T> list)
    {
        if (list.Count == 0)
        {
            Debug.LogWarning("No data to save.");
            return;
        }

        var type = typeof(T);
        var properties = type.GetProperties();

        // CSV 헤더 생성
        string csv = string.Join(Separator.ToString(), Array.ConvertAll(properties, p => p.Name)) + "\n";

        // 데이터 추가
        foreach (var obj in list)
        {
            string line = string.Join(Separator.ToString(), Array.ConvertAll(properties, p => Quote + p.GetValue(obj)?.ToString() + Quote));
            csv += line + "\n";
        }

        // 파일로 저장
        File.WriteAllText(filePath, csv);
        Debug.Log("Data saved to " + filePath);
    }
}
post-custom-banner

0개의 댓글