유니티3D 안드로이드 플랫폼 XML WRITE LOAD 질문입니다.

조회수 2447회
string filename = "Quests";

Type[] questType = { typeof(QUEST) };

FileStream fs = new FileStream(Path.Combine(Application.persistentDataPath,filename+".txt"), FileMode.Create);

StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);

XmlSerializer serializer = new XmlSerializer(typeof(QuestContainer), questType);

serializer.Serialize(sw, questContainer);

sw.Close();

위는 지정된 파일에 WRITE하기 위한 방법입니다.

string filename = "Quests";

Type[] questType = { typeof(QUEST) };

XmlSerializer serializer = new XmlSerializer(typeof(QuestContainer), questType);

TextReader fs = new StreamReader(Application.persistentDataPath + filename + ".txt");

QuestContainer = (QuestContainer)serializer.Deserialize(fs);

fs.Close();

위는 지정된 파일을 LOAD하기 위한 방법입니다.

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

public class QuestContainer
{
    private List<QUEST> confirmed = new List<QUEST>();
    private List<QUEST> complete = new List<QUEST>();
    private List<QUEST> possible = new List<QUEST>();
    private List<QUEST> im_possible = new List<QUEST>();

    public List<QUEST> Confirmed
    {
        get { return confirmed; }
        set { confirmed = value; }
    }

    public List<QUEST> Complete
    {
        get { return complete; }
        set { complete = value; }
    }

    public List<QUEST> Possible
    {
        get { return possible; }
        set { possible = value; }
    }

    public List<QUEST> im_Possible
    {
        get { return im_possible; }
        set { im_possible = value; }
    }
}

위는 QuestContainer 클래스입니다.

public class QUEST
{
    public string Questname { get; set; }
    public string Description { get; set; }
    public string Class { get; set; }
    public int Level { get; set; }
    public int STR { get; set; }
    public int CON { get; set; }
    public int INT { get; set; }
    public int WIS { get; set; }
    public int DEX { get; set; }
    public string Title { get; set; }
    public string Item { get; set; }
    public QUEST_TYPE questType { get; set; }
    public DIFFICULTY difficulty { get; set; }
    public EXPEDIENT eXPEDIENT { get; set; }
    public QUEST_REWARD questReward { get; set; }
    public string target { get; set; }
    public int count { get; set; }
    public bool canClear { get; set; }

    public QUEST()
    {

    }

    public QUEST(string Questname,string Description,string Class,int level,int str,int con, int Int, int wis, int dex,string title,string item,  QUEST_TYPE QuestType, DIFFICULTY Difficulty, QUEST_REWARD quest_reward, EXPEDIENT EXPEDIENT, string Target, int Count, bool canclear)
    {
        this.Description = Description;
        this.Questname = Questname;
        this.questType = QuestType;
        this.difficulty = Difficulty;
        this.eXPEDIENT = EXPEDIENT;
        this.questReward = quest_reward;
        this.Class = Class;
        this.Level = level;
        this.STR = str;
        this.CON = con;
        this.INT = Int;
        this.WIS = wis;
        this.DEX = dex;
        this.Title = title;
        this.Item = item;
        this.target = Target;
        this.count = Count;
        this.canClear = canclear;
    }
 }

위는 Quest클래스입니다.

<?xml version="1.0" encoding="utf-8"?>
<QuestContainer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Confirmed>
    <QUEST>
      <Questname>시작</Questname>
      <Description>이제 시작이에요!</Description>
      <Class>ALL</Class>
      <Level>0</Level>
      <STR>0</STR>
      <CON>0</CON>
      <INT>0</INT>
      <WIS>0</WIS>
      <DEX>0</DEX>
      <Title />
      <Item />
      <questType>ROOP</questType>
      <difficulty>EASY</difficulty>
      <eXPEDIENT>MOVE</eXPEDIENT>
      <questReward>GOLD</questReward>
      <target>Bank</target>
      <count>10</count>
      <canClear>false</canClear>
    </QUEST>
  </Confirmed>
  <Complete />
  <Possible />
  <im_Possible />
</QuestContainer>

위는 xml파일 입니다. 안드로이드 플랫폼에선 .txt로 변경하여 사용중입니다.

QuestContainer의 리스트에 따라 4가지 프로세스로 나뉘어 xml파일에 저장이됩니다.

read는 이상없이 잘 되나,

게임 중 QuestContainer에 리스트 내용을 바꿔주고 write를 해주는데,

다시 불러올 때 아무 변경이 없는 내용이 불러와지는걸 보니, write에 문제가 있는 것 같은데 이유를 알 수 없네요.

1 답변

  • 다음과 같이 하니 안드로이드에서 잘 동작하네요. 파일의 내용을 불러와서 값을 바꿔서 쓴 다음 다시 불러와서 출력해 봤습니다.

    pathForDocumentsFile에서 경로를 불러오세요. 그리고 파일을 불러올때 실패하게되면 resources의 파일을 불러오는 방식을 이용했습니다.

    using UnityEngine;
    using System.Collections;
    using System.Xml;
    using System.Collections.Generic;
    using System.Xml.Serialization;
    using System.IO;
    using System.Text;
    using System;
    
    
    public class NewBehaviourScript : MonoBehaviour {
        QuestContainer container;
        void Start () {
            loadXML ();
            Debug.Log ("###before###");
            foreach (QUEST quest in container.Confirmed) {
                Debug.Log (quest.Description);
                quest.Description="!!!"+quest.Description;
            }
    
            writeXML ();
            loadXML ();
            Debug.Log ("###after###");
            foreach (QUEST quest in container.Confirmed) {
                Debug.Log (quest.Description);
            }
    
    
        }
    
        void loadXML(){
            try{
                TextReader fs = new StreamReader(pathForDocumentsFile("Catalog.txt"));
                var serializer = new XmlSerializer(typeof(QuestContainer));
                container = serializer.Deserialize(fs) as QuestContainer;
                fs.Close();
            }
            catch(Exception e){
                TextAsset textAsset = (TextAsset) Resources.Load("Catalog");  
                var serializer = new XmlSerializer(typeof(QuestContainer));
                StringReader stream = new StringReader (textAsset.ToString ());
                container = serializer.Deserialize(stream) as QuestContainer;
                stream.Close();
            }
        }
    
        void writeXML(){
            var serializer = new XmlSerializer (typeof(QuestContainer));
            var stream = new FileStream(pathForDocumentsFile("Catalog.txt"), FileMode.Create);
            StreamWriter sw = new StreamWriter (stream, Encoding.UTF8);
            serializer.Serialize(sw, container);
            stream.Close();
        }
    
        public string pathForDocumentsFile( string filename ) 
        {
            if (Application.platform == RuntimePlatform.IPhonePlayer)
            {
                string path = Application.dataPath.Substring( 0, Application.dataPath.Length - 5 );
                path = path.Substring( 0, path.LastIndexOf( '/' ) );
                return Path.Combine( Path.Combine( path, "Documents" ), filename );
            }
            else if(Application.platform == RuntimePlatform.Android)
            {
                string path = Application.persistentDataPath; 
                path = path.Substring(0, path.LastIndexOf( '/' ) ); 
                return Path.Combine (path, filename);
            } 
            else 
            {
                string path = Application.dataPath; 
                path = path.Substring(0, path.LastIndexOf( '/' ) );
                return Path.Combine (path, filename);
            }
        }
    }
    

    그리고 serializer를 이용하기 위해서는 각 클래스에 다음과 같은 annotation을 붙여주어야 합니다.

    using System.Xml.Serialization;
    using System.Collections.Generic;
    
    [XmlRoot("QuestContainer")]
    public class QuestContainer{
        [XmlArray("Confirmed")]
        [XmlArrayItem("QUEST")]
        public List<QUEST> Confirmed = new List<QUEST> ();
    }
    
    
    public class QUEST{
        public string Questname;
        public string Description;
        public int Level;
    }
    
    • 정말 토나오네요. 프로그램 로직짜는것보다 파일 하나 입출력하는게 더 힘드니 무슨 .. 화딱지나서 죽겠네요. annotation을 붙일 때 리스트 별로 하나씩 붙이는 겁니까? 답변 감사합니다. 지금은 너무 고통스러워서 있다가 실행 확인하겠습니다.. 정우진 2016.2.18 18:09
    • 네. 리스트별로 다 따로 붙입니다. 정두식 2016.2.18 18:43
    • 아 정말 감사합니다.. ㅡㅡ write가 안되는게 annotation을 안 붙여준 것 때문이었나요? application.persistent로 접근한 것은 같은데.. 왜 안되는지 이유를 알 수 없었는데 아 쾌감 때문에 미치겠네요. 정우진 2016.2.18 20:02
    • Json를 사용하시면 훨씬 편하게 할 수 있을거 같습니다. https://github.com/SaladLab/Json.Net.Unity3D 이놈 한번 써보세용. SangMin Choi 2016.3.15 23:22

답변을 하려면 로그인이 필요합니다.

Hashcode는 개발자들을 위한 무료 QnA 사이트입니다. 계정을 생성하셔야만 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)

ᕕ( ᐛ )ᕗ
로그인이 필요합니다

Hashcode는 개발자들을 위한 무료 QnA사이트 입니다. 계정을 생성하셔야만 글을 작성하실 수 있습니다.