유니티 csv 파일 읽기 ( Unity csv file read ) 수정 19.11.15

19.11.15 개행 문자에 대한 이슈로 수정.

 

 

[ 버전 A ]

Resource폴더에 있는 CSV 파일을 읽는 용도로 사용한다.

Resource폴더를 참조할 때 파일 확장자가 없음에 유의.

 

19.11.15 : \n을 LINE_SPLIT_RE로 사용하기 때문에 개행문자를 입력못하는 문제가 있어서 <br>을 대신 사용하도록 변경. 개행을 엔터로 해버리면 아래코드에서는 The given key was not present in the dictionary.오류가 나니 주의

참조 : http://blog.kpaper.com/2017/06/unity-csv-reader-c.html

 

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

public class CSVReader
{
    static string SPLIT_RE = @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))";
    static string LINE_SPLIT_RE = @"\r\n|\n\r|\n|\r";
    static char[] TRIM_CHARS = { '\"' };
    
    public static List<Dictionary<string, object>> Read(string file)
    {
        var list = new List<Dictionary<string, object>>();
        TextAsset data = Resources.Load (file) as TextAsset;
        
        var lines = Regex.Split (data.text, LINE_SPLIT_RE);
        
        if(lines.Length <= 1) return list;
        
        var header = Regex.Split(lines[0], SPLIT_RE);
        for(var i=1; i < lines.Length; i++) {
            
            var values = Regex.Split(lines[i], SPLIT_RE);
            if(values.Length == 0 ||values[0] == "") continue;
            
            var entry = new Dictionary<string, object>();
            for(var j=0; j < header.Length && j < values.Length; j++ ) {
                string value = values[j];
                value = value.TrimStart(TRIM_CHARS).TrimEnd(TRIM_CHARS).Replace("\\", "");

                value = value.Replace("<br>", "\n"); // 추가된 부분. 개행문자를 \n대신 <br>로 사용한다.
                value = value.Replace("<c>", ",");

                object finalvalue = value;
                int n;
                float f;
                if(int.TryParse(value, out n)) {
                    finalvalue = n;
                } else if (float.TryParse(value, out f)) {
                    finalvalue = f;
                }
                entry[header[j]] = finalvalue;
            }
            list.Add (entry);
        }
        return list;
    }
}

 

 

사용 예시. 파싱은 (int) 나 (string) 등으로 충분.

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

public class Test : MonoBehaviour
{

    public int _exp = 0;

    void Start()
    {
        List<Dictionary<string, object>> data = CSVReader.Read("knightIdle - playerChar");

        for (var i = 0; i < data.Count; i++)
        {
            Debug.Log("index " + (i).ToString() + " : " + data[i]["attack"] + " " + data[i]["attackSpeed"] + " " + data[i]["criticalChance"]);
        }

        _exp = (int)data[0]["attack"];
        Debug.Log(_exp);
    }
}

 

 

-------------------------------------------------------------------------------------------------------------

 

[ 버전 B ]

Streaming 폴더를 사용해야할 일이있어서 Streaming 폴더를 임시로 경로지정. 

여기서는 Resources.Load 대신에 StreamReader를 사용함. 파일명에서는 확장자까지.

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

public class CSVReader
{
    static string SPLIT_RE = @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))";
    static string LINE_SPLIT_RE = @"\r\n|\n\r|\n|\r";
    static char[] TRIM_CHARS = { '\"' };
    
    public static List<Dictionary<string, object>> Read(string file)
    {
        var list = new List<Dictionary<string, object>>();
        //TextAsset data = Resources.Load (file) as TextAsset;
        
        string source;
        StreamReader sr = new StreamReader(Application.dataPath + "/StreamingAssets" + "/" + file);
        source = sr.ReadToEnd();
        sr.Close();

        //var lines = Regex.Split(data.text, LINE_SPLIT_RE);

        var lines = Regex.Split(source, LINE_SPLIT_RE);

        if (lines.Length <= 1) return list;
        
        var header = Regex.Split(lines[0], SPLIT_RE);
        for(var i=1; i < lines.Length; i++) {
            
            var values = Regex.Split(lines[i], SPLIT_RE);
            if(values.Length == 0 ||values[0] == "") continue;
            
            var entry = new Dictionary<string, object>();
            for(var j=0; j < header.Length && j < values.Length; j++ ) {
                string value = values[j];
                value = value.TrimStart(TRIM_CHARS).TrimEnd(TRIM_CHARS).Replace("\\", "");
                object finalvalue = value;
                int n;
                float f;
                if(int.TryParse(value, out n)) {
                    finalvalue = n;
                } else if (float.TryParse(value, out f)) {
                    finalvalue = f;
                }
                entry[header[j]] = finalvalue;
            }
            list.Add (entry);
        }
        return list;
    }
}

 

 

-------------------------------------------------------------------------------------------------------------------------------------------

모바일과 에디터로 분리.

// 에디터 혹은 PC 버전일 경우에는 : 즉 밸런싱 테스트용 빌드일 경우에는! 스트리밍 에셋에서 불러옵니다.
#if (UNITY_EDITOR || UNITY_STANDALONE)

        // 경로에 파일 존재하는지 확인
        string dir = Application.dataPath + "/StreamingAssets/" + file + ".csv";
        if (!File.Exists(dir))
        {
            Debug.Log(file + "파일이 존재하지않습니다.");
            return list;
        }
        
        string source;
        StreamReader sr = new StreamReader(Application.dataPath + "/StreamingAssets/" + file + ".csv");
        source = sr.ReadToEnd();
        sr.Close();
        var lines = Regex.Split(source, LINE_SPLIT_RE);
#else

        TextAsset data = Resources.Load (file) as TextAsset;
        var lines = Regex.Split(data.text, LINE_SPLIT_RE);
#endif

 

 

 

[ 공통 : 오브젝트 형식 데이터 파싱 ]

 오브젝트형식으로 리턴되는 파싱은 int.Parse(data.ToString())

// 오브젝트 -> float로 파싱
public float FloatParse(object obj)
{
    return float.Parse(obj.ToString());
}

// 오브젝트 -> int로 파싱
public int IntParse(object obj)
{
    return int.Parse(obj.ToString());
}

 

[ 공통 : csv 편집기 ]

 엑셀보다는 Rons CSV Editor를 추천함. 엑셀은 무겁기도하고, 열고있으면 Violation Error 나기도하고.

 https://www.ronsplace.eu/Products/RonsEditor/Download

 

 

댓글

Designed by JB FACTORY