C#프로그래밍 19 : 파일입출력, 직렬화/역직렬화

LeeWonjin·2022년 6월 1일
0

[학부]C#프로그래밍

목록 보기
19/21

파일 입출력 개요

  • 파일 : 데이터의 묶음
  • 디렉터리 : 파일이 위치하는 주소
  • System.IO 내 아래 클래스가 파일입출력에 관련됨
    • File : 정적 메소드. 파일 생성/삭제/이동/조회
    • FileInfo : File과 동일. 인스턴스 메소드.
    • Directory : 정적 메소드. 디렉터리 생성/삭제/이동/조회
    • DirectoryInfo : Directory와 동일. 인스턴스 메소드.
static void Main(string[] args)
{
    string username = "CEDPT";
    string directory = $"C:/Users/{username}/Downloads";
    Console.WriteLine("=====Directories=====");

    var directories = (from dir in Directory.GetDirectories(directory)
                        let info = new DirectoryInfo(dir)
                        select new
                        {
                            name = info.Name,
                            attr = info.Attributes
                        }).ToList();
    foreach (var d in directories)
        Console.WriteLine($"{d.name} : {d.attr}");

    Console.WriteLine("\n=====Files=====");

    var files = (from file in Directory.GetFiles(directory)
                    let info = new FileInfo(file)
                    select new
                    {
                        name = info.Name,
                        len = info.Length,
                        attr = info.Attributes
                    }).ToList();
    foreach (var f in files)
        Console.WriteLine($"{f.name} : {f.len},{ f.attr} ");
}

System.IO.Stream

  • 스트림 : 입출력을 위해 어딘가에서 메모리로 데이터를 차례로 가져올 수 있는 통로
    • 파일입출력의 경우 "HDD/SSD --> 메모리"
    • 순차접근, 임의접근 모두 가능

닷넷에 추상클래스 System.IO.Stream이 제공되고, 아래 대표적인 파생클래스가 있음.

  • FileStream
  • NetworkStream
  • BufferdStream

FileStream

파일 생성/열기

아래와 같이 사용 가능.

Stream st1 = new FileStream("a.txt", FileMode.OpenOrCreate);

생성자 두 번째 인수는 파일모드.

  • FileMode.Create : 생성
  • FileMode.Open : 열기
  • FileMode.OpenOrCreate : 없으면 생성, 있으면 열기
  • FileMode.Truncate : 파일 비우고 열기
  • FileMode.Append : 추가(덧붙임)모드로 열기

BitConverter

스트림은 바이트 단위로 동작. 현재 어떤 시스템인지 (리틀엔디안/빅엔디안) 확인필요

읽고 쓸 때BitConverter클래스를 사용해 바이트<--->일반적인 데이터 변환수행 필요

byte[] bytes = BitConverter.GetBytes(123456);
long bytesTOlong = BitConverter.ToInt64(bytes, 0);

파일 쓰기

Stream클래스의 Write(), WriteByte() 메소드 사용

public override void Write( // 호출하면 Position프로퍼티 읽은 바이트수 만큼 증가
  byte[] array,
  int offset,
  int count
);
public override void WriteByte(byte value); // 호출하면 Position프로퍼티 값 1 증가
static void Main(string[] args)
{
    Stream outs = new FileStream("a.txt", FileMode.Open);
    byte[] bytes = BitConverter.GetBytes('a');
    outs.Write(bytes, 0, bytes.Length); // a 저장
    outs.Close();
}

파일 읽기

public override int Read( // 호출하면 Position프로퍼티 읽은 바이트수 만큼 증가
  byte\[] array,
  int offset,
  int count
);
public override int ReadByte(); // 호출하면 Position프로퍼티 값 1 증가
static void Main(string[] args)
{
    byte[] bytes = new byte[10];
    Stream ins = new FileStream("a.txt", FileMode.Open); // 내용 a
    ins.Read(bytes, 0, bytes.Length);
    Console.WriteLine(BitConverter.ToChar(bytes, 0)); // a
    ins.Close();
}

임의접근

Seek()메소드 사용으로 포지션 이동가능

static void Main(string[] args)
{
    Stream outs = new FileStream("a.txt", FileMode.Create);
    outs.Seek(5, SeekOrigin.Current);
    outs.WriteByte(0x62); // "     b" 저장
    outs.Close();
}

using키워드

파일닫기

코드블록 안에 파일입출력 관련 코드를 몰아넣고, 파일스트림 생성 문장 앞에 using키워드를 붙일 수 있음

--> 이 경우 코드블록이 끝날 때 Stream.Dispose()가 호출되어 파일이 닫힘

( 스트림객체.Close()와 다름없음 )

static void Main(string[] args)
{
    using (Stream st = new FileStream("c.txt", FileMode.OpenOrCreate))
    {
        byte[] bytes = BitConverter.GetBytes('b');
        st.Write(bytes, 0, bytes.Length);
    }
}

별칭 지시문

using fs = System.IO.FileStream;
namespace ConsoleApp4
{
    class Program
    {
        static void Main(string[] args)
        {
            using (Stream st = new fs("c.txt", FileMode.OpenOrCreate))
            {
                byte[] bytes = BitConverter.GetBytes('b');
                st.Write(bytes, 0, bytes.Length);
            }
        }
    }
}

이진 데이터 처리

스트림에 이진데이터를 읽거나 쓸 때 사용 할 수 있는 클래스가 있다.

  • BinaryWriter
  • BinaryReader
static void Main(string[] args)
{
	BinaryWriter binWr = new BinaryWriter(new FileStream("b.txt", FileMode.OpenOrCreate));

	binWr.Write(53);
	binWr.Write('a');
	binWr.Write("gorani");
	binWr.Write(5.3);

	binWr.Close();
}
static void Main(string[] args)
{
    BinaryReader binRr = new BinaryReader(new FileStream("b.txt", FileMode.OpenOrCreate));
    Console.WriteLine(binRr.ReadInt32()); // 정수출력
    binRr.Close();
}

텍스트 파일 처리

아스키 인코딩은 한 바이트가 한 문자를 나타내므로, 바이트 오더 문제가 없고 내용을 바로 읽을 수 있음.

  • StreamWriter
  • StreamReader

static void Main(string[] args)
{
    using (StreamWriter sw = new StreamWriter(new FileStream("d.txt", FileMode.Create)))
    {
        sw.WriteLine(5353);
        sw.WriteLine("gorani");
    }
    using (StreamReader sr = new StreamReader(new FileStream("d.txt", FileMode.Open)))
    {
        while (sr.EndOfStream == false)
            Console.WriteLine(sr.ReadLine());
    }
}

객체 직렬화

복합 데이터 형식을 스트림에 쓰고 읽기 위한 작업

저장할 순서를 정하고 쓰는 것을 직렬화, 그 순서에 따라 읽는 것을 역직렬화라고 함.

직렬화/역직렬화 대상의 어트리뷰트 수식

[Serializable] 어트리뷰트를 클래스 선언부 앞(위)에 붙여 직렬화할 것으로 표시

클래스 내에서 직렬화하지 않을(할 수 없는) 필드 앞(위)에는 [NonSerialized] 어트리뷰트를 붙여 표시.

BinaryFormatter

BinaryFormatter는 직렬화를 하기 위한 클래스.

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;

namespace Program
{
    [Serializable]
    class Gorani
    {
        public string name;
        public int id;

        [NonSerialized]
        public string I_hate_serialization;

        public override string ToString()
        {
            return $"name : {name} , id : {id} , I_hate_serialization : {I_hate_serialization}";
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // 직렬화
            using (Stream ws = new FileStream("c.txt", FileMode.OpenOrCreate))
            {
                BinaryFormatter serializer = new BinaryFormatter();

                Gorani gorani = new Gorani();
                gorani.name = "wonjin";
                gorani.id = 123;

                serializer.Serialize(ws, gorani);
            }

            // 역직렬화
            using (Stream rs = new FileStream("c.txt", FileMode.Open))
            {
                BinaryFormatter desirializer = new BinaryFormatter();

                Gorani gorani = (Gorani)desirializer.Deserialize(rs);
                Console.WriteLine(gorani); // name : wonjin , id : 123
            }
        }
    }
}
 
profile
노는게 제일 좋습니다.

0개의 댓글