From 5db096060e46540086b44eb54b9ad8f253c4620e Mon Sep 17 00:00:00 2001 From: art <artbiit@naver.com> Date: Sat, 17 May 2025 16:50:41 +0900 Subject: [PATCH] =?UTF-8?q?[ADD]=20CSV=20Loader=20=EC=B4=88=EC=95=88=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/1_Script/System/CSVLoader.cs | 118 +++++++++++++++++++++++ Assets/1_Script/System/CSVLoader.cs.meta | 11 +++ 2 files changed, 129 insertions(+) create mode 100644 Assets/1_Script/System/CSVLoader.cs create mode 100644 Assets/1_Script/System/CSVLoader.cs.meta diff --git a/Assets/1_Script/System/CSVLoader.cs b/Assets/1_Script/System/CSVLoader.cs new file mode 100644 index 0000000..5ee3138 --- /dev/null +++ b/Assets/1_Script/System/CSVLoader.cs @@ -0,0 +1,118 @@ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using UnityEngine; +using UnityEngine.Networking; +/// <summary> +/// CSV 데이터를 다양한 소스에서 Pull 방식으로 로드할 수 있는 클래스입니다. +/// 호출 측에서 MoveNext()를 통해 처리 타이밍을 제어하세요. +/// </summary> +public static class CSVLoader +{ + /// <summary>CSV 파싱 로직 정의</summary> + public interface IParser<T> + { + T Parse(string[] columns); + } + + /// <summary>로딩 진행 상태 메타데이터</summary> + public struct Progress + { + public int TotalRows; + public int RowsLoaded; + } + + /// <summary>URL(HTTP)로부터 다운로드하여 파싱</summary> + public static IEnumerator<Progress> Download<T>(string url, + IParser<T> parser, + List<T> outList) + { + using var uwr = UnityWebRequest.Get(url); + var operation = uwr.SendWebRequest(); + // 요청이 완료될 때까지 대기 (Progress 타입 반환은 요청 상태 표시용) + while (!operation.isDone) + { + yield return new Progress { TotalRows = 0, RowsLoaded = 0 }; + } + + if (uwr.result != UnityWebRequest.Result.Success) + { + Logger.LogError($"CSVLoader: Download failed '{url}': {uwr.error}"); + yield break; + } + + string text = uwr.downloadHandler.text; + foreach (var prog in ProcessText(text, parser, outList)) + yield return prog; + } + + /// <summary>절대 경로의 파일을 읽어 파싱</summary> + public static IEnumerator<Progress> LoadFromFile<T>(string filePath, + IParser<T> parser, + List<T> outList) + { + if (!File.Exists(filePath)) + { + Logger.LogError($"CSVLoader: File not found '{filePath}'"); + yield break; + } + string text = File.ReadAllText(filePath); + foreach (var prog in ProcessText(text, parser, outList)) + yield return prog; + } + + /// <summary>StreamingAssets 내 상대 경로 또는 URL로부터 로드</summary> + public static IEnumerator<Progress> LoadFromStreamingAssets<T>(string relativePath, + IParser<T> parser, + List<T> outList) + { + string fullPath = Path.Combine(Application.streamingAssetsPath, relativePath); + if (fullPath.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + { + var downloadEnum = Download(fullPath, parser, outList); + while (downloadEnum.MoveNext()) + yield return downloadEnum.Current; + } + else + { + var fileEnum = LoadFromFile(fullPath, parser, outList); + while (fileEnum.MoveNext()) + yield return fileEnum.Current; + } + } + + /// <summary>Resources 폴더 내 TextAsset로부터 로드</summary> + public static IEnumerator<Progress> LoadFromResources<T>(string resourcePath, + IParser<T> parser, + List<T> outList) + { + var ta = Resources.Load<TextAsset>(resourcePath); + if (ta == null) + { + Logger.LogError($"CSVLoader: Resource not found '{resourcePath}'"); + yield break; + } + string text = ta.text; + foreach (var prog in ProcessText(text, parser, outList)) + yield return prog; + } + + /// <summary>텍스트를 실제 파싱하여 Progress를 반환하는 내부 모듈</summary> + static IEnumerable<Progress> ProcessText<T>(string text, + IParser<T> parser, + List<T> outList) + { + var lines = text.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); + int total = lines.Length; + // 첫 번째 줄은 헤더이므로 무시 + // 두 번째 줄은 설명이므로 무시 + for (int i = 2; i < total; i++) + { + var cols = lines[i].TrimEnd('\r').Split(','); + outList.Add(parser.Parse(cols)); + yield return new Progress { TotalRows = total, RowsLoaded = i + 1 }; + } + } +} \ No newline at end of file diff --git a/Assets/1_Script/System/CSVLoader.cs.meta b/Assets/1_Script/System/CSVLoader.cs.meta new file mode 100644 index 0000000..36638a1 --- /dev/null +++ b/Assets/1_Script/System/CSVLoader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1b37f2c717edfd748bf3173c734fee71 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: