ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [06강] 파일 입출력
    프로그래밍/C# 2022. 5. 2. 22:49

    목차

    스트림(Stream)
    직렬화(Serialize)
    정리

     

    스트림(Stream)

      파일 스트림 : 파일을 읽고 쓰는 것.

      스트림? 파일, 네트워크 등에서 데이터를 바이트 단위로 읽고 쓰는 클래스

      Stream class는 상위 기본 클래스이다.

      - 상속 클래스들 : FileStream, MemoryStream, NetworkStream, SqlFileStream 등

      using System.IO 선언

     

      파일 스트림?

      - 파일 입출력을 다루는 기본 클래스

      - System.Object

        + System.MarshalByRefObject

           + System.IO.Stream

              + System.IO.FileStream

      - byte[] 배열로 데이터를 읽거나 저장함 -> 형변환이 요구됨

      - SteamWriter/StreamReader + BinaryWriter/BinaryReader와 사용

      - 파일 정보 설정에 사용

        public FileStream( string path, FileMode mode, FileAccess access );

        - FileMode 열거형 : Append, Create, CreateNew, Open, OpenOrCreate, Truncate

        - FileAccess 열거형 : Read, ReadWrite, Write

     

      텍스트 파일 처리

      - StreamWriter, StreamReader

      - 텍스트 파일의 특징

        - 기본 단위 : 1바이트

        - 아스키코드 기반

      - 아스키 코드를 유니코드로 인코딩

     

      StreamWriter

      - 역할 : 파일 쓰기

      - 상속 계층 구조

      - System.Object

        + System.MarshalByRefObject

          + System.IO.TextWriter

            + System.IO.StreamWriter

      - public class StreamWriter : TextWriter

      - 객체 생성과 해제

    static void Main(string[] args)
    {
    	FileStream fs = new FileStream("test.txt", FileMode.Create);
    	StreamWriter sw = new StreamWriter(fs);
    	sw.Close();
    }

      - using문

        using(StreamWriter sw = new StreamWriter( new FileStream("test.txt", FileMode.Create ) ) {  // 파일 입출력 처리 }

        : 파일 입출력 처리 블럭이 끝남과 동시에 Close를 자동으로 호출해 준다.

      

    예시 코드

    static void Main(string[] args)
    {
        int value = 12;
        float value2 = 3.14f;
        string str1 = "Hello World";
    
        using (StreamWriter sw = new StreamWriter(new FileStream("Test2.txt", FileMode.Create)))
        {
            sw.WriteLine(value);
            sw.WriteLine(value2);
            sw.WriteLine(str1);
        }
    }

      

      StreamReader

      - 역할 : 파일 읽기

      - 상속 계층 구조

      - System.Object

        + System.MarshalByRefObject

          + System.IO.TextReader

            + System.IO.StreamReader

      - public class StreamReader : TextReader

      - 읽기 메서드 : Read(), ReadLine(). string ReadLine()

    using (StreamReader sr = new StreamReader(new FileStream("Test3.txt", FileMode.Open)))
    {
        int value = int.Parse(sr.ReadLine());
        float value2 = float.Parse(sr.ReadLine());
        string str1 = sr.ReadLine();
        Console.WriteLine(value);
        Console.WriteLine(value2);
        Console.WriteLine(str1);
    }

     

      string 데이터 분리

      - string str = "C언어: 90 C#언어: 100 컴퓨터구조:70";

      public string[] Split(params char[] separator)

      string.Split(new char[] { ',', '.', ' ' } );

     

      이진 파일 읽기와 쓰기

      - BinaryWriter/BinaryReader

      - 메소드

        - ReadBoolean(), ReadByte(), ReadBytes(int32), ReadChar(), ReadChars(Int32), ReadDecimal(), ReadDouble(), 

          ReadInt16(), ReadInt32(), ReadInt64(), ReadSByte(), ReadSingle(), ReadString(), ReadUInt16(), ReadUInt32(),

          ReadUInt64(), Write()

      - BinaryReader(Stream), BinaryReader(Stream, Encoding), BinaryReader(Stream, Encoding, Boolean)

        Encoding을 생략하면 기본적으로 UTF-8로 인코딩이 된다.

     

    직렬화(Serialize)

      Binary Read Write등을 통해서 이진파일을 저장할 수 있으며, 구조체 멤버 변수의 값을 일일히 저장할 수 있다. 하지만 일일히 하다보니 번거롭다.

      시리얼라이즈를 통해 개별적으로 하던 부분을 한꺼번에 할 수 있으며, 구조체나 클래스로 명시한 멤버 변수의 값을 한꺼번에 저장하거나 한꺼번에 읽어낼 수 있는 등의 기능을 제공하고 있다

     

      - StreamWriter/StreamReader와 BinaryWriter/BinaryReader : 기본 데이터형만 저장 및 읽기

      - 구조체, 클래스 저장 및 읽기 : FileStream, BInaryFormatter

     

      BinaryFormatter

      - BinaryFormatter 네임 스페이스

        using System.Runtime.Serialization.Formatters.Binary;

      - 대상 설정

    [Serializable]
    struct A
    {
    }
    
    [Serializable]
    class A
    {
    }

     

      - BinaryFormatter의 메서드

        - public void Serialize( Stream serializationStream, object graph ) : 메모리에 들어있는 데이터를 저장하는 역할

        - public object Deserialize( Stream serializationStream ) : 저장되어있는 데이터를 읽어내서 데이터, 클래스 안에 넣어주는 역할. 리턴 타입이 object이기 때문에 캐스트 연산자를 통해 형변환을 해 주어야 한다.

        - 예시 코드

    using System.Runtime.Serialization.Formatters.Binary;
    
    struct MyData
    {
        public int var1;
        public float var2;
        public string str1;
    }
        
    static void Main(string[] args)
    {
         MyData[] myDatas = new MyData[2];
    
         myDatas[0].var1 = 1;
         myDatas[0].var2 = 0.5f;
         myDatas[0].str1 = "Test1";
    
         myDatas[1].var1 = 3;
         myDatas[1].var2 = 1.5f;
         myDatas[1].str1 = "Test2";
    
         // 내용 저장하기
         using (FileStream fs1= new FileStream("Test2.dat",FileMode.Create))
         {
             BinaryFormatter bf = new BinaryFormatter();
             bf.Serialize(fs1, myDatas);
         }
    
         // 읽어내기
         MyData[] resultData;
    
         using (FileStream fs2 = new FileStream("Test2.dat", FileMode.Open))
         {
             BinaryFormatter bf2 = new BinaryFormatter();
             resultData = (MyData[]) bf2.Deserialize(fs2);
         }
    
         for (int i = 0; i < resultData.Length; i++)
         {
             Console.WriteLine($"{resultData[i].var1}, {resultData[i].var2}, {resultData[i].str1}");
         }
     }

     

      역직렬화(deserialize)

      - 직렬화 대상에서 제외

      - [NonSerialize]

      - 예시 코드

    using System.Runtime.Serialization.Formatters.Binary;
    
    [Serializable]
    struct MyNewData
    {
        public int var1;
        public float var2;
        [NonSerialized] public string str1;
    }
    
    static void Main(string[] args)
    {
        MyNewData[] myNewDatas = new MyNewData[2];
    
        myNewDatas[0].var1 = 1;
        myNewDatas[0].var2 = 0.5f;
        myNewDatas[0].str1 = "Test3";
    
        myNewDatas[1].var1 = 5;
        myNewDatas[1].var2 = 2.5f;
        myNewDatas[1].str1 = "Test4";
    
        using (FileStream fs1 = new FileStream("Test3.dat", FileMode.Create))
        {
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(fs1, myNewDatas);
        }
    
        MyNewData[] resultDatas;
    
        using (FileStream fs2 = new FileStream("Test3.dat", FileMode.Open))
        {
            BinaryFormatter bf2 = new BinaryFormatter();
            resultDatas = (MyNewData[]) bf2.Deserialize(fs2);
        }
    
        for (int i = 0; i < resultDatas.Length; i++)
        {
            Console.WriteLine($"{resultDatas[i].var1}, {resultDatas[i].var2}, {resultDatas[i].str1}");
        }
    }

     

      컬렉션의 직렬화

      - 컬렉션과 제네릭 : 같은 데이터형의 임의의 메모리 또는 연속적인 메모리를 다룰 수 있도록 하는 클래스

      - 제네릭 : C++의 템플릿과 같다. 저장하고자 하는 데이터 타입을 외부에서 고정설정하여 사용하는 형태

      - ArrayList, List<T>

      - 제네릭을 이용한 직렬화

     

    정리

     

    '프로그래밍 > C#' 카테고리의 다른 글

    [08강] 클래스  (0) 2022.05.31
    [07강] 프로젝트 실습 - 스마트 밥솥  (0) 2022.05.29
    [05강] 배열  (0) 2022.04.24
    [04강] C# 기본 문법  (0) 2022.04.12
    [03강] 데이터형, 변환, 표준 입력형식  (0) 2022.04.12
Designed by Tistory.