TIL

C# .csv파일 변환 방법과 예시

추운날_너를_기다리며 2024. 11. 26. 02:23

글의 목적 

.csv 파일을 읽어서 데이터를 클래스나 다른 형태로 활용하는 방법은 다양한 언어와 라이브러리에서 가능합니다.

여기서는 C#에서 .csv 파일을 읽고 데이터를 클래스에 매핑하는 예제를 소개하겠습니다.

 

1. .csv 파일 분석

ItemCode,Name,ItemType,Prefab
# This file contains item data for the game
# ItemType :
# 0 = Material
# 1 = Equipment
# 2 = Junk
1000,Wood,0,Wood
1001,SolidWood,0,SolidWood
1010,Iron,0,Iron
1011,Steel,0,Steel
1100,Garbage,2,Garbage

각 줄의 역할:

  1. 1번째 줄 (헤더):
    • ItemCode, Name, ItemType, Prefab로 데이터 필드 이름을 정의합니다.
  2. 2~3번째 줄 (주석):
    • 주석은 파일을 이해하기 위한 설명으로, 데이터가 아니므로 무시합니다.
  3. 4번째 줄 이후 (데이터):
    • 실제 데이터는 4번째 줄부터 시작됩니다.

2. 클래스 정의

    1) ItemType 열을 관리할 Enum 정의

    2) 데이터를 담을 Item 클래스 정의

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ResourceWar.Server
{
    public enum ItemType
    {
        Material = 0, // 재료
        Equipment = 1, // 장비
        Junk = 2       // 쓰레기
    }

    public class ItemClass
    {
        public int ItemCode { get; set; }   // 아이템 코드
        public string Name { get; set; }   // 아이템 이름
        public ItemType Type { get; set; } // 아이템 타입 (Enum)
        public string Prefab { get; set; } // 프리팹 이름

        public override string ToString()
        {
            return $"ItemCode: {ItemCode}, Name: {Name}, Type: {Type}, Prefab: {Prefab}";
        }
    }

}

 

3. CSV 데이터 읽기 및 변환

     1) System.IO를 활용한 CSV 데이터 읽기

      CSV 데이터를 읽어 Item 객체 리스트로 변환합니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

namespace ResourceWar.Server
{
    public static class LoadCSV
    {
        /// <summary>
        /// Item 데이터를 저장하는 정적 Dictionary
        /// Key: ItemCode, Value: Item 객체
        /// </summary>
        public static Dictionary<int, ItemClass> Items { get; private set; } = new Dictionary<int, ItemClass>();

        public static void LoadItemsFromCSV()
        {
            // Resources 폴더 내 경로 (파일 확장자 제외)
            string path = "Items/ItemData";

            // CSV 파일 읽기
            TextAsset csvData = Resources.Load<TextAsset>(path);
            if (csvData == null)
            {
                Logger.LogError($"Failed to load CSV file at {path}. Check if the file exists in Resources.");
                return;
            }

            // 줄 단위로 분리
            string[] lines = csvData.text.Split('\n');

            // 데이터 파싱 (헤더 및 주석 무시)
            Items.Clear(); // 기존 데이터 초기화
            for (int i = 3; i <lines.Length; i++)
            {
                string line = lines[i].Trim();

                // 빈 줄은 건너뜀
                if (string.IsNullOrWhiteSpace(line))
                    continue;

                string[] values = line.Split(',');

                try
                {
                    int itemCode = int.Parse(values[0]); // ItemCode를 Key로 사용

                    var item = new ItemClass
                    {
                        ItemCode = itemCode,
                        Name = values[1],
                        Type = (ItemType)int.Parse(values[2]),
                        Prefab = values[3]
                    };

                    // Dictionary에 추가
                    if (!Items.ContainsKey(itemCode))
                    {
                        Items.Add(itemCode, item);
                    }
                    else
                    {
                        Debug.LogWarning($"Duplicate ItemCode found: {itemCode}. Skipping this entry.");
                    }
                }
                catch (Exception ex)
                {
                    Debug.LogError($"Error parsing line {i + 1}: {line}. Exception: {ex.Message}");
                }
            }

            Debug.Log($"Loaded {Items.Count} unique items from CSV.");
        }
    }
}

 

4. 실행 결과

ItemCode: 1000, Name: Wood, Type: Material, Prefab: Wood
ItemCode: 1001, Name: SolidWood, Type: Material, Prefab: SolidWood
ItemCode: 1010, Name: Iron, Type: Material, Prefab: Iron
ItemCode: 1011, Name: Ironstone, Type: Material, Prefab: Ironstone
ItemCode: 1100, Name: Garbage, Type: Junk, Prefab: Garbage

 

5. CSV 데이터 활용

     특정 조건에 따라 아이템 필터링으로 아이템 리스트에서 특정 타입만 추출:

var materialItems = items.FindAll(item => item.Type == ItemType.Material);

Console.WriteLine("Material Items:");
foreach (var item in materialItems)
{
    Console.WriteLine(item);
}

 

6. 결론

위 코드를 활용하면 ItemData.csv 파일 데이터를 효과적으로 읽고 Item 객체로 변환해 사용할 수 있습니다. 특정 조건에 따라 데이터를 필터링하거나, Dictionary를 통해 빠르게 검색할 수도 있습니다.