-
[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