6강. 파일입출력

InSung-Na·2023년 7월 29일
0

나우캠퍼스_C#

목록 보기
7/7
post-thumbnail

1. 파일 스트림(Stream)

스트림

  • 파일, 네트워크 등에서 데이터를 바이트 단위로 읽고 쓰는 클래스
  • Stream class는 상위 기본 클래스
    • FileSteam
    • MemoryStream
    • NetworkStream
    • SqllFileStream
  • using System.IO로 선언

FileStream

  • 파일 입출력을 다루는 기본 클래스
  • byte[] 배열로 데이터를 읽거나 저장함
    -> 형변환이 요구됨
  • StreamWriter / StreamReader
  • BinaryWriter / BinaryReader
public FileStream(
	string path,		//경로
    FileMode mode,		//Append, Create, CreateNew, Open, OpenOrCreate, Truncate
    FileAccess access	//Read, ReadWrite, Write
)

텍스트 파일 처리

  • StreamWriter, StreamReader
  • 텍스트 파일 특징
    • 기본단위: 1바이트
    • 아스키코드: 기반
  • C# 인코딩: 아스키코드 -> 유니코드

StreamWriter

  • 파일쓰기
  • public class StreamWriter : TextWriter

    상속구조

    • System.Object
      • System.MarshalByRefObject
        • System.IO.TextWriter
          • System.IO.StreamWriter
static void Main(string[] args)
{
	//실행파일이 존재하는 Debug 디렉토리에 생성됨
	FileStream fs = new FileStream("test.txt", FileMode.Create);
    StreamWriter sw = new StreamWriter(fs);
    //파일 입출력 처리
    sw.WriteLine(12);
    sw.WriteLine(3.14f);
    sw.Write("Hello World");
    sw.Close();
    
    //아래와 같이 사용 시 Close() 메서드 사용 불필요, 자동 Close() 실행
    //단순 쓰기용으로 사용한다면 FileStream 불필요, "파일명"만 작성해도 실행가능
    using (StreamWriter sw2 = new StreamWriter(new FileStream("test2.txt", FileMode.Create)))
    {
    	//파일 입출력 처리
    }
}

StreamReader

  • 파일읽기
  • public class StreamReader : TextReader

    상속구조

    • System.Object
      • System.MarshalByRefObject
        • System.IO.TextReader
          • System.IO.StreamReader
static void Main(string[] args)
{
	//단순 읽기용으로 사용한다면 FileStream 불필요, "파일명"만 작성해도 실행가능
	FileStream fs = new FileStream("test.txt", FileMode.Open, FileAccess.Read);
    StreamReader sr = new StreamReader(fs);
    //파일 입출력 처리
    var value = int.Parse(sr.ReadLine());
    var value2 = float.Parse(sr.ReadLine());
    var str1 = sr.ReadLine();
    sr.Close();
    
    Console.WriteLine("{0}, {1}, {2}", value, value2, str1);
}

string 데이터 분리

  • string.Split 활용
string str = "C언어: 90 C#언어: ,100 컴퓨터.구조: 70";

var str_Element = str.Split(',', '.', ' ');
foreach(var element in str_Element)
    Console.WriteLine(element);
--------------------------------------------------------------
C언어:
90
C#언어:

100
컴퓨터
구조:
70
계속하려면 아무 키나 누르십시오 . . .

바이너리 파일 읽고 쓰기

  • 위와 동일한 형식으로 진행
  • 쓰기모드
using (BinaryWriter bw = new BinaryWriter(new FileStream("test.dat", FileMode.Create)))
{
    //파일 입력 처리
    bw.Write(12);
    bw.Write(3.14f);
    bw.Write("Hello World");
}
  • 읽기모드
    BinaryReader(Stream, Encoding, Boolean)
    • Stream: 타겟(FileStream)
    • Encoding: 인코딩 설정(default = UTF-8)
    • Boolean: 객체 소멸 시 입력스트림 닫기 여부(default=false)
int var1;
float var2;
string str1;

using (BinaryReader br = new BinaryReader(File.Open("test.data", FileMode.Open)))
{
    //파일 입력 처리
    var1 = br.ReadInt32();
    var2 = br.ReadSingle();
    str1 = br.ReadString();
}
Console.WriteLine("{0} {1} {2}", var1, var2, str1);
--------------------------------------------------------------------
12 3.14 Hello World

2. 직렬화(Serialize)

직렬화

  • 기존의 StreamWriter/StreamReader(바이너리 포함)
    -> 기본 데이터형만 저장 및 읽기 가능
  • BinaryFormatter 네임스페이스
    • 구조체, 클래스 저장 및 읽기를 지원함
[Serializable]
Struct A	//클래스도 사용가능
{
	//파라미터 입력
}
public void Serialize(
	Stream serializationStream,
    object graph
)

//Deserialize은 object형임으로 기본형으로 형변환 필요
public object Deserialize(
	Stream serializationStream
)

역직렬화(deserialize)

  • 직렬화 대상에서 제외
[Serializable]
class TestClass
{
	int nValue;
    [NonSerialize]
    string strMessage;
    //내용
}

직렬화와 역직렬화 예시

  • 직렬화 시도 후 직렬화된 데이터 읽기는 정상적으로 출력됨
  • 역직렬화로 직렬화가 되지 않은 데이터 읽기는 공백으로 출력됨
static void 직렬화()
{
    DATA[] Data = new DATA[2];
    Data[0].var1 = 1;
    Data[0].var2 = 0.5f;
    Data[0].str1 = "Test1";
    Data[1].var1 = 2;
    Data[1].var2 = 1.5f;
    Data[1].str1 = "Test2";

    using (FileStream fs1 = new FileStream("test.dat", FileMode.Create))
    {
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(fs1, Data);
    }

    DATA[] ResultData;

    using (FileStream fs2 = new FileStream("test.dat", FileMode.Open))
    {
        BinaryFormatter bf2 = new BinaryFormatter();
        ResultData = (DATA[])bf2.Deserialize(fs2);
    }

    for(int i=0;i<2;i++)
        Console.WriteLine("{0} {1} {2} {3}", 
            ResultData[i].var1, ResultData[i].var2, ResultData[i].str1, 1);
}
---------------------------------------------------------------------------
1 0.5  1
2 1.5  1

컬렉션의 직렬화

  • 같은 데이터형의 임의의 메모리 또는 연속적인 메모리를 다룰 수 있도록 하는 클래스
  • ArrayList, List<T>
  • 제네릭(<>)을 이용한 직렬화
[Serializable]
struct Data
{
    public int data;
    public string str;
    public Data(int data1, string str1)
    {
        data = data1;
        str = str1;
    }
}

static void 제네릭을_이용한_직렬화()
{
    List<Data> ResultList;
    List<Data> DataList = new List<Data>();
    DataList.Add(new Data(7, "test1"));
    DataList.Add(new Data(12, "test2"));
    DataList.Add(new Data(19, "test3"));

    using (FileStream fs1 = new FileStream("test.dat", FileMode.Create))
    {
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(fs1, DataList);
    }

    using (FileStream fs2 = new FileStream("test.dat", FileMode.Open))
    {
        BinaryFormatter bf2 = new BinaryFormatter();
        ResultList = (List<Data>)bf2.Deserialize(fs2);
    }

    for (int i=0;i<ResultList.Count;i++)
        Console.WriteLine("{0} {1}", ResultList[i].data, ResultList[i].str);
}

3. 정리

입출력 단위클래스사용빈도
바이트File, FileStream + BitConverter1
텍스트StreamWriter, StreamReader + FileStream3
이진BinaryWriter, BinaryReader + FileStream5
구조체와 클래스[Serializable] + BinaryFormatter6
구조체와 클래스[Serializable] + 컬랙션 + BinaryFormatter6

4. Reference

0개의 댓글