본문 바로가기
UNITY/유니티게임스쿨

CSV Parser

by 램플릿 2024. 7. 19.

csv 런타임에 파싱하는것과 csv를 미리 scripable object로 저장했을때
속도 차이는 50% ~ 90% 그 이상까지도 속도 차이가 난다.

 

 

엑셀파일

 

 

엑셀을 .csv로 export했을때 텍스트파일의 모습

 

 

CSV 파서

using UnityEngine;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.IO;

public class CSVParser : MonoBehaviour
{
    public static List<string[]> Parse(string filePath)
    {
        List<string[]> parsedData = new List<string[]>();

        try
        {
            using (StreamReader reader = new StreamReader(filePath))
            {
                while (!reader.EndOfStream)
                {
                    string line = reader.ReadLine();
                    string[] fields = ParseCSVLine(line);
                    parsedData.Add(fields);
                }
            }
        }
        catch (IOException e)
        {
            Debug.LogError("Error reading CSV file: " + e.Message);
        }

        return parsedData;
    }

    private static string[] ParseCSVLine(string line)
    {
        List<string> fields = new List<string>();
        string pattern = @"(?:^|,)(?=[^""]|("")?)""?((?(1)[^""]*|[^,""]*))""?(?=,|$)";

        foreach (Match match in Regex.Matches(line, pattern))
        {
            fields.Add(match.Groups[2].Value.Trim());
        }

        return fields.ToArray();
    }
}

 

 

 

CSV 파서 데이터

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;

public class CSVParserEditorWindow : EditorWindow
{
    private string csvFilePath = "";
    private List<string[]> parsedData;
    private Vector2 scrollPosition;

    [MenuItem("Tools/CSV Parser")]
    public static void ShowWindow()
    {
        GetWindow<CSVParserEditorWindow>("CSV Parser");
    }

    private void OnGUI()
    {
        GUILayout.Label("CSV Parser", EditorStyles.boldLabel);

        EditorGUILayout.Space();

        csvFilePath = EditorGUILayout.TextField("CSV File Path", csvFilePath);

        if (GUILayout.Button("Browse"))
        {
            string path = EditorUtility.OpenFilePanel("Select CSV File", "", "csv");
            if (!string.IsNullOrEmpty(path))
            {
                csvFilePath = path;
            }
        }

        if (GUILayout.Button("Parse CSV"))
        {
            if (string.IsNullOrEmpty(csvFilePath))
            {
                EditorUtility.DisplayDialog("Error", "Please specify a CSV file path.", "OK");
                return;
            }

            if (!File.Exists(csvFilePath))
            {
                EditorUtility.DisplayDialog("Error", "File not found at the specified path.", "OK");
                return;
            }

            parsedData = CSVParser.Parse(csvFilePath);
            Debug.Log(parsedData);

            var csvData = ScriptableObject.CreateInstance<CSVData>();
            
            csvData.SetData(parsedData);
            EditorUtility.SetDirty(csvData);
            AssetDatabase.CreateAsset(csvData, "Assets/20240719/csvData.asset");
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
            
            EditorUtility.DisplayDialog("Success", $"Parsed {parsedData.Count} rows from the CSV file.", "OK");
        }

        EditorGUILayout.Space();

        if (parsedData != null && parsedData.Count > 0)
        {
            EditorGUILayout.LabelField("Parsed Data:", EditorStyles.boldLabel);

            scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
            
            for (int i = 0; i < parsedData.Count; i++)
            {
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField($"Row {i}:", GUILayout.Width(50));
                EditorGUILayout.LabelField(string.Join(", ", parsedData[i]));
                EditorGUILayout.EndHorizontal();
            }

            EditorGUILayout.EndScrollView();
        }
    }
}

 

 

 

csvData

using System;
using UnityEngine;
using System.Collections.Generic;

[Serializable]
public struct CSVDataModel
{
    public int data1;
    public int data2;
    public int data3;
    public int data4;
}

[CreateAssetMenu(fileName = "New CSV Data", menuName = "CSV/CSV Data")]
public class CSVData : ScriptableObject
{
    [SerializeField]
    private List<CSVDataModel> models = new List<CSVDataModel>();
    public void SetData(List<string[]> newData)
    {
        foreach (var stringse in newData)
        {
            CSVDataModel model = new CSVDataModel();
            
            if (!int.TryParse(stringse[0], out model.data1))
            {
                model.data1 = 0;
            }
            if (!int.TryParse(stringse[1], out model.data2))
            {
                model.data2 = 0;
            }
            if (!int.TryParse(stringse[2], out model.data3))
            {
                model.data3 = 0;
            }
            if (!int.TryParse(stringse[3], out model.data4))
            {
                model.data4 = 0;
            }   
            
            models.Add(model);
        }
    }
}