Clolent

Boxing 과 Unboxing


형변환 할때 주로 변환한다. 

Boxing 이란 값을 참조 형태로 바꾸는

Unboxig 이란 참조하는 것을값 형태로 바꾸는 기법이라고 하는데, 

어떠한 오브젝트를 쓰려고 가져왔는데, 오브젝트 자체를 쓰진 못하니 사용할 수 있게,

강제로 형변환을 해야한다.


자세히 한번 알아봅시다 ! 중요하다고 한다.


Delegate ( 대리자 )


Delegate 라는 것은 함수의 이름을 변경하여 호출하는 형태,

선언형식 : delegae 반환값 함수이름 ( 매개변수 )

함수 포인터 라고 생각하면 된다. 


Sum 이란 함수가 있다.

Func 라는 곳에 Sum 의 주소를 담는다면 앞으로

Func( ) 을 호출하면 결국은 Sum 이 호출된다.


※ 괄호 열고 닫고는 호출한다는 의미이고, 괄호가 없는 것은 그냥 주소를 담는다는 뜻이다.


※ GOF : 디자인 패턴 : 예를 들면 싱글턴, 상태패턴 같은 것


※ 상태패턴 : STATE 라는 변수하나르 두고, 여러 상태들 ( 로딩, 로고, 타이틀, 옵션 등등 ) 을 관리이를 원래 Switch 를 통해 관리하여야하지만, Delegate 를 사용한다면 상태가바뀔때마다, Delegate의 대입만 바꿔주면 된다. 


※ FSM : 유한상태머신 : 로고 타이틀 왓닸다하는 것 등 제한된 상태에서 왔다갔다하는 것 


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


Action ( 대리자와 거의 같다. )


Delegate 를 편리하게 호출하기 위해 미리 선언해 노흔 방식

Action : 반환형이 없는 대리자


System.Action 대리자 이름 ;

System.Action<Type> 대리자 이름




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


Event ( 대리자와 거의 같다. )


특정 시점에 함수를 연결하여 호출하거나 연결을 해제하여 호출을 중지 시킬 수 있는 메시지 함수.

선언형식 : event 대리자( or Action ) 이벤트이름

구독자 패턴 / 관찰자 패턴 / 옵저버 패턴 이라고도 부름


신문 구독을 생각하자 구독자가 있으면 매번 같은시간 신문주고 구도자 없으면 아무일도 안하면 된다 ! 



만약 저 MyEvent += Pring 를 10번 반복하고나서 Start 에서 저렇게 호출하면 Print 가 10번 호출된다고 함. 


일반적으로 Event 에 1개만 넣어서 사용한다. 



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


재미있는 예제 // 클래스 포인터에 관하여

Class A {
void Print( ){
cout << "Hello World" ;
}
}

A *pt = NULL ;
pt -> print( ) ;

오류가 일어나지 않고잘 돌아간다. ! 


Class A {
int a ;
void Print( ){
cout << "Hello World" ;
++a ;
}
}

A *pt = NULL ;
pt -> print( ) ;

Hello World 가 출력된 다음 오류가 일어나다. 왜? a는 존재하지 않는다. 

생각해보자 포인터가 NULL 을 가리키고는 있지마 이미 print 라는 함수는 메모리 어딘가에 존재 하는 것이다.
그렇다면 두번째 예제는 왜 오류인가? a 에 접근하려 했지만 a는 메모리 상에 존재하지 않기 때문이다.

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


파일 출력 ( 쓰기 ) 


using Sysem.IO ;


FileStream 변수명(File) = new FileStream( 경로 , FileMode.Create ) ;




파일에 이제 무언가 써내려가고 싶을때

TextWriter 변수명(Writer) = new StreamWriter( 위의 File ) ;

Writer.Write( " 쓰고싶은말 " ) ;


파일을 이제 다을때

파일을 열어서 무언가를 했다면 반드시 반드시 닫아야한다.


Writer.Close( );


※ 만약 파일이 안생길때 using UnityEditor 추가하고 AssetDatabase.Refresh( ) ; 를 마지막 줄에 추가해주면 된다.



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


파일 입력 ( 읽기 )


파일을 읽어올때에는 쓰기 부분과 비슷하되 몇군데가 다르다.


주의 해야할 부분은 FileMode.Open 이라는 것과 기존의 TextWriter 였던 것이 TextReader 로 바뀌었다는 것이다.


그리고 이 C# 에서 파일 입출력을 할때에는 앞으로 꼭! 텍스트 파일 첫줄이라던가 매 줄이라던가에 숫자를 통해서 몇줄을 읽어야 하는지 혹으 이 줄이 몇 어절 로 이루어져 있는지 힌트를 주는것이 편하다는 것이다 !!'


만약 텍스트 파일에

3

A

B

C

라고 넣었다면, 읽을 때에는


        TextReader txtReader = new StreamReader(fs);

        int cnt = int.Parse(txtReader.ReadLine());

        string txt = "";

        for (int a = 0; a < cnt; ++a)

        {

            txt += txtReader.ReadLine() + "\n";

        }


이런식으로 3줄을 읽어 올수 있다.


그리고 위 사진에서 맨 마지막을 보라 기존 쓰기(입력) 과정에선 TextWriter 만 닫았지만 출력(읽기) 과정에서는

파일을 열었던 fs 자체도 닫아주고 있다. 다른 문제 발생이 생기는 것을 막기위해서 이다.



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


연습한 코드


using UnityEngine;

using System.Collections;

using System.IO;

using UnityEditor;


public class IOstream : MonoBehaviour {


    class PlayerInfo

    {

        public string name;

        public string job;

        public int HP;

        public int MP;

        public int STR;

        public int DEX;

        public int INT;

    }

// Use this for initialization

void Start () {

        SaveTextFile();

        LoadTextFile();

        //"C:/Users/User/Documents/VR"

    }


    // Update is called once per frame

    void Update () {

}

    void SaveTextFile()

    {

        string dataPath = Application.dataPath + "/Resources/";

        string filename = "myTxt.txt";


        // 파일 열기

        FileStream fs = new FileStream( dataPath + filename , FileMode.Create);

        Debug.Log(" 파일 주소 : " + dataPath);


        // 파일 출력

        TextWriter txtWriter = new StreamWriter(fs);

        txtWriter.Write("3\nSteve Jobs, Warrior, 650, 50,69,25,17\n" +

            "Bill Gates, Magician, 350, 450, 27, 19,82\n" +

            "Lee Gun Hee, Archer, 450,250,35,60,30");


        //파일 닫기

        txtWriter.Close(); // 파일을 열어서 무언갈 했으면 반드시 닫아줘야 한다.

        AssetDatabase.Refresh(); // 

    }


    void LoadTextFile()

    {

        string dataPath = Application.dataPath + "/Resources/";

        string filename = "myTxt.txt";


        // 파일 열기

        FileStream fs = new FileStream(dataPath + filename, FileMode.Open);


        // 파일 출력

        TextReader txtReader = new StreamReader(fs);

        int cnt = int.Parse(txtReader.ReadLine());

        string txt = "";

        string[] result = new string[cnt];

        PlayerInfo[] player = new PlayerInfo[cnt];


        for (int a = 0; a < cnt; ++a)

        {

            txt = txtReader.ReadLine();

            string[] sprite = txt.Split(',');

            player[a] = new PlayerInfo();

            player[a].name = sprite[0].Trim();

            player[a].job = sprite[1].Trim();

            player[a].HP = int.Parse(sprite[2].Trim());

            player[a].MP = int.Parse(sprite[3].Trim());

            player[a].STR = int.Parse(sprite[4].Trim());

            player[a].DEX = int.Parse(sprite[5].Trim());

            player[a].INT = int.Parse(sprite[6].Trim());

        }


        for (int a = 0; a < cnt; ++a)

        {

           result[a] += player[a].name + " " + player[a].job +

                " " + player[a].HP+ " " + player[a].MP+ " " 

                + player[a].STR+ " " + player[a].DEX + " "

                + player[a].INT + " "  ;

        }

        Debug.Log(result[0]);

        Debug.Log(result[1]);

        Debug.Log(result[2]);

        //파일 닫기

        txtReader.Close(); // 파일을 열어서 무언갈 했으면 반드시 닫아줘야 한다.

        fs.Close();  // 읽을경우는 이것까지 닫아줘야한다.

        AssetDatabase.Refresh(); // 


    }

} 



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


실제 출시할때 바뀌어야할 코드


왜 ? 어떤 OS에 팔릴지 모르고, OS 마다 접근권한이 다를수있기 때문 바뀐 Load 함수


    void LoadTextFile_Finish()

    {

        // 유니티 상에서

        string filename = "myTxt2.txt";


        // 파일 열기

        TextAsset asset = (TextAsset)Resources.Load(filename, typeof(TextAsset));

        TextReader textReader2 = new StringReader(asset.text);


        // 파일 출력

        int cnt = int.Parse(textReader2.ReadLine());

        string txt = "";

        string[] result = new string[cnt];

        PlayerInfo[] player = new PlayerInfo[cnt];


        for (int a = 0; a < cnt; ++a)

        {

            txt = textReader2.ReadLine();

            Debug.Log(txt);

            string[] sprite = txt.Split(',');

            foreach (string b in sprite)

            {

                Debug.Log(b);

            }

            player[a] = new PlayerInfo();

            player[a].name = sprite[0].Trim();

            player[a].job = sprite[1].Trim();

            player[a].HP = int.Parse(sprite[2].Trim());

            player[a].MP = int.Parse(sprite[3].Trim());

            player[a].STR = int.Parse(sprite[4].Trim());

            player[a].DEX = int.Parse(sprite[5].Trim());

            player[a].INT = int.Parse(sprite[6].Trim());

        }


        for (int a = 0; a < cnt; ++a)

        {

            result[a] += player[a].name + " " + player[a].job +

                 " " + player[a].HP + " " + player[a].MP + " "

                 + player[a].STR + " " + player[a].DEX + " "

                 + player[a].INT + " ";

        }

        Debug.Log(result[0]);

        Debug.Log(result[1]);

        Debug.Log(result[2]);

        //파일 닫기

        textReader2.Close(); // 이것만 닫으면 된다 filestream 을 사용안하기때문

        AssetDatabase.Refresh(); // 


    }


※ CSV 파일( comma-separated values ) , ( 컴마 ) 로 구분지어 지는 파일 

엑셀에서 열리는 Text 파일이므로 많이 쓰인다고함 

내가 위에서 재미로 만들었던 캐릭터 3명의 정보 파일이 확장하는 txt 이지만 사실상 CSV 파일이다.


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


Binary 파일


바이너리를 사용해야하는 이유 

- 텍스트 파일은 쓸데없는 정보가 너무 많다 ! 

- 용량이 훨씬 작다.

- 텍스트 파일은 그냥 읽어 올수가 없다.

- 바이너리는 그냥 읽어온다.

- 어느정도의 암호화 


자료형 상과없이 Write 를 사용하면된다.


TextWriter -> BinaryWriter 

그리고 저장단계에서 확장자가 bytes 혹은 byte 로 해야한다.


바꾼 두 함수 코드 


    void SaveBinaryFile() // 바이너리 파일로 저장

    {

        string dataPath = Application.dataPath + "/Resources/";

        string filename = "MyBinaryTxt.bytes";


        // 파일 열기

        FileStream fs = new FileStream(dataPath + filename, FileMode.Create);

        Debug.Log(" 파일 주소 : " + dataPath);


        // 파일 출력

        BinaryWriter txtWriter = new BinaryWriter(fs);

        txtWriter.Write(3);

        txtWriter.Write("Steve AAA");

        txtWriter.Write("Warrior");

        txtWriter.Write(650);

        txtWriter.Write(50);

        txtWriter.Write(69);

        txtWriter.Write(25);

        txtWriter.Write(17);

        txtWriter.Write("Bill BBB");

        txtWriter.Write("Magician");

        txtWriter.Write(350);

        txtWriter.Write(450);

        txtWriter.Write(27);

        txtWriter.Write(19);

        txtWriter.Write(82);

        txtWriter.Write("Lee CCC");

        txtWriter.Write("Archer");

        txtWriter.Write(450);

        txtWriter.Write(250);

        txtWriter.Write(35);

        txtWriter.Write(60);

        txtWriter.Write(30);


        //파일 닫기

        txtWriter.Close(); // 파일을 열어서 무언갈 했으면 반드시 닫아줘야 한다.

        

    }

============================================================

    void LoadBinaryFile_Developing() // 바이너리파일 읽어오기

    {

        string dataPath = Application.dataPath + "/Resources/";

        string filename = "MyBinaryTxt.bytes";


        // 파일 열기

        FileStream fs = new FileStream(dataPath + filename, FileMode.Open);


        // 파일 출력

        BinaryReader txtReader = new BinaryReader(fs);

        int cnt = txtReader.ReadInt32();

        string txt = "";

        string[] result = new string[cnt];

        PlayerInfo[] player = new PlayerInfo[cnt];


        for (int a = 0; a < cnt; ++a)

        {

            player[a] = new PlayerInfo();

            player[a].name = txtReader.ReadString();

            player[a].job = txtReader.ReadString();

            player[a].HP = txtReader.ReadInt32();

            player[a].MP = txtReader.ReadInt32();

            player[a].STR = txtReader.ReadInt32();

            player[a].DEX = txtReader.ReadInt32();

            player[a].INT = txtReader.ReadInt32();

        }


        for (int a = 0; a < cnt; ++a)

        {

            result[a] += player[a].name + " " + player[a].job +

                 " " + player[a].HP + " " + player[a].MP + " "

                 + player[a].STR + " " + player[a].DEX + " "

                 + player[a].INT + " ";

        }

        Debug.Log(result[0]);

        Debug.Log(result[1]);

        Debug.Log(result[2]);

        //파일 닫기

        txtReader.Close(); // 파일을 열어서 무언갈 했으면 반드시 닫아줘야 한다.

        fs.Close();  // 읽을경우는 이것까지 닫아줘야한다.

        AssetDatabase.Refresh(); // 


    }


댓글 로드 중…

블로그 정보

Clolent - 커피물조절달인

최근에 게시된 글