프로그램/유니티 스크립트 소스

[유니티 스크립트 소스] CSV Reader / Write

코더 제로 2022. 7. 17. 05:01
728x90
반응형
using System.Collections.Generic;
using UnityEngine;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;

public class CsvDemo : MonoBehaviour
{
    public struct CsvData
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public bool IsBool { get; set; }
        public float Float { get; set; }
        
        public override string ToString() =>$"{Id},{Name},{IsBool},{Float}";
    }

    public string m_FilePath;
    private string[] m_Headers = new string[] { "Id", "Name", "IsBool", "Float"};

    void Start()
    {
        // Write
        var csvs = new List<CsvData>()
        {
            new CsvData { Id = 1, Name = "Name1", IsBool = true, Float = float.MaxValue },
            new CsvData { Id = 2, Name = "Name2", IsBool = true, Float = float.MinValue },
            new CsvData { Id = 3, Name = "Name3", IsBool = false, Float = default(float) }
        };

        WriteCsv(m_FilePath, m_Headers, csvs);

        // Read
        List<Dictionary<string, object>> csvReaders = ReadCsv(m_FilePath);

        for (int i = 0; i < csvReaders.Count; i++)
        {
            foreach (KeyValuePair<string, object> item in csvReaders[i])
            {
                Debug.Log($"{item.Key} : {item.Value}");
            }
        }

        // Debug 1
        Debug.Log($"Id : {csvReaders[0]["Id"]} Name: {csvReaders[0]["Name"]} " +
            $"IsBool : {csvReaders[0]["IsBool"]} Float : {csvReaders[0]["Float"]}");

        // Debug 2
        int id = 0;        
        if(TryParseInt(csvReaders[0]["Id"].ToString(), out id))
        {
            Debug.Log(id);
        }

        // Debug 3
        float Float = 0;
        if (TryParseFloat(csvReaders[0]["Float"].ToString(), out Float))
        {
            Debug.Log(Float);
        }

        // Debug 4
        bool Bool = false;
        if (TryParseBool(csvReaders[0]["IsBool"].ToString(), out Bool))
        {
            Debug.Log(Bool);
        }
    }
    
    public static void WriteCsv(string filePath, string[] headers, List<CsvData> csvDatas)
    {
        FileStream fs = File.Create(filePath);
        StreamWriter sw = new StreamWriter(fs);

        if(headers.Length != 0)
        {
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < headers.Length; i++)
            {
                sb.Append(headers[i]);
                sb.Append(",");
            }

            sw.WriteLine(sb.ToString());
        }

        for (int i = 0; i < csvDatas.Count; i++)
        {
            sw.WriteLine(csvDatas[i].ToString());
        }

        sw.Close();
        fs.Close();
    }

    private static string split = @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))";
    private static string lineSplite = @"\r\n|\n\r|\n|\r";
    private static char[] trims = { '\"' };

    public static List<Dictionary<string, object>> ReadCsv(string filePath)
    {
        var list = new List<Dictionary<string, object>>();
        FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
        var sr = new StreamReader(fs);
        string source = sr.ReadToEnd();
        sr.Close();
        fs.Close();

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

        if (lines.Length <= 1) return list;

        var header = Regex.Split(lines[0], split);

        for (var i = 1; i < lines.Length; i++)
        {
            var values = Regex.Split(lines[i], split);
            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(trims).TrimEnd(trims).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;
    }       

    public static bool TryParseInt(string value, out int number)
    {
        bool success = int.TryParse(value, out number);

        if (success)
            return true;

        else
        {
            Debug.Log($"Attempted conversion of '{value ?? "<null>"}' failed.");
            return false;
        }
    }

    public static bool TryParseFloat(string value, out float number)
    {
        bool success = float.TryParse(value, out number);

        if (success)
            return true;

        else
        {
            Debug.Log($"Attempted conversion of '{value ?? "<null>"}' failed.");
            return false;
        }
    }

    public static bool TryParseBool(string value, out bool number)
    {
        bool success = bool.TryParse(value, out number);

        if (success)
            return true;

        else
        {
            Debug.Log($"Attempted conversion of '{value ?? "<null>"}' failed.");
            return false;
        }
    }
}
728x90
반응형