ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [C#] JsonConvert, StreamWrite, StreamReader, File.Exists
    C# Visual Studio/2 2024. 1. 4. 11:28

    게임의 데이터를 파일로 저장하고, 다시 파일을 데이터로 불러오는 기능을 구현해 보았다.

    위 기능을 구현하기 위한 순서는, 스크립트 내에 저장하고 싶은 데이터를 직렬화 (serialize) 시킨 후, 파일에 쓰고(StreamWrite)(저장) , 저장된 파일을 불러오기 위해, 파일에 적힌 데이터를 역직렬화(deserialize) 시킨 후, 파일에 있는 데이터를 읽어온다(StreamReader)(불러오기).

    직렬화란 자바 언어에서 사용되는 Object 또는 Data를 다른 컴퓨터의 자바 시스템에서도 사용 할수 있도록 바이트 스트림(stream of bytes)형태로 연속적인(serial) 데이터로 변환하는 포맷 변환 기술을 일컫는다.

    직렬화를 글로써 접하면 처음에는 이해하기 어려울수 있어서, 데이터를 냉장고에 비유해서 그림을 만들어보았다.

    위와같이 냉장고의 복합적인 모든정보들을 "글자(문자?,한글?)" 로 통일시켜 바꾼것이다.

    기능을 구현하기위해 직렬화 메서드 JsonConvert.SerializeObject , 역직렬화 메서드 JsonConvert.DeserializeObject 를 사용하였는데, 이 메서드를 사용하기위해선, JSON 라이브러리를 참조 추가 해야한다.

    Nuget 패키지 관리로 들어가서 json 이라고 검색후, Newtonsoft.Json 항목을 설치하면 된다.

    그리고, 파일을 읽고 쓰기위한 스트림으로 StreamReader와 StreamWriter 를 사용하였는데, 이 클래스 들은 System.IO 네임스페이스에 선언되어 있으므로 사용하기 위해선 System.IO를 using 해줘야 한다.

     

    using Newtonsoft.Json;
    using System.IO;
    
    namespace SaveLoadTest
    {
        internal class Program
        {
            struct Item // 저장할 데이터 타입
            {
                public string Name { get; set; }
                public int Price { get; set; }
                public Item(string name, int price)
                {
                    Name = name;
                    Price = price;
                }
            }
    
            static void Main(string[] args)
            {
                Item Weapon = new Item("sword", 100);         // 두개의 데이터 생성
                Item Armor = new Item("glove", 50);
                List<Item> inventory = new List<Item>();      // 데이터 리스트 생성
    
                string filePath = "C:\\VisualStudioProject\\SaveLoadTest"; // 파일경로
    
                void SaveAndReadTest()
                {
                    inventory.Add(Weapon);
                    foreach (Item item in inventory)
                    {
                        Console.WriteLine($"{item.Name}, {item.Price}"); // sword, 100
                    }
    
                    using (StreamWriter sw = new StreamWriter(filePath + "\\saveData.json")) // filePath(파일경로) + \\파일명.json 으로 파일생성
                    {
                        sw.Write(JsonConvert.SerializeObject(inventory));  // 파일에 inventory 를 직렬화하여 데이터 저장
                    }
    
                    inventory.Add(Armor);
                    foreach (Item item in inventory)
                    {                                                     // sword, 100
                        Console.WriteLine($"{item.Name}, {item.Price}");  // glove, 50
                    }
    
                    using (StreamReader sr =  new StreamReader(filePath + "\\saveData.json"))
                    {
                        inventory = JsonConvert.DeserializeObject<List<Item>>(sr.ReadToEnd()); // saveData.json 파일데이터를 List<Item>으로 역직렬화 하여 inventory 에 저장
                    }
    
                    foreach (Item item in inventory)
                    {
                        Console.WriteLine($"{item.Name}, {item.Price}"); // sword, 100
                    }
                }
    
                SaveAndReadTest();
            }
        }
    }

     

    추가로, 파일의 데이터를 불러올때, 파일이 없을경우, 예외처리가 입력되어있지않아서 오류가 발생할수있다.

    나는 File.Exists() 메서드를 이용해서 예외처리를 해주었다.

    File.Exists() 메서드는 string 타입의 파일 경로를 매개 변수로 사용하여, 파일이 존재하면 true를 반환하고, 파일이 없거나, 접근할수있는 권한이 없으면 false를 반환한다.

    경로가 유효하지 않거나 null 및 문자열의 길이가 0일 경우에도 false를 반환한다.

    if(File.Exists(filePath + "\\saveData.json"))
    {
        using (StreamReader sr = new StreamReader(filePath + "\\saveData.json"))
        {
            inventory = JsonConvert.DeserializeObject<List<Item>>(sr.ReadToEnd());
        }
    }

    마지막으로, 오늘 구현해본 기능을 그림으로 정리해보았다.

     

    파일을 읽고 쓰는 Stream 에는 더많은 기능들이 오버로딩되어있다. 상황에 따라 알맞게 쓰면 될듯싶다.

     

Designed by Tistory.