MemoryStream
MemoryStream은 메모리에 Byte 데이터를 순서대로 읽고 쓰는 작업을 수행합니다.
// MemoryStream
MemoryStream memoryStream = new MemoryStream();
// MemoryStream에 넣을 byte 데이터
byte[] byArrData1 = BitConverter.GetBytes(1234); // 1234는 int
byte[] byArrData2 = BitConverter.GetBytes(5678); // 5678은 int
// MemoryStream에 byArrData1을 적재
memoryStream.Write(byArrData1, 0, byArrData1.Length);
// MemoryStream에 byArrData2을 적재
memoryStream.Write(byArrData2, 0, byArrData2.Length);
// MemoryStream 닫기
memoryStream.Close();
위의 예제는 MemoryStream을 생성하여 MemoryStream에 Byte 데이터들을 적재하는 예제입니다.
하나 하나 보면
6번줄까지 실행했을 때 MemoryStream이 열렸고 byArrData1(1234)와 byArrData2(5678)이 생성되었습니다.
11번줄까지 실행했을 때 각각의 Byte 데이터들이 MemoryStream에 차례대로 적재가 되었습니다.
이렇게 적재가 끝난 이후에 MemoryStream의 Position을 확인하면 "8"을 가리키고 있습니다.
즉, 현재 Position은 다음 데이터가 들어갈 위치 이자 현재 읽고 있는 위치를 의미 합니다.
이제 이렇게 Memory에 넣은 데이터를 역직렬화 해보겠습니다.
// MemoryStream
MemoryStream memoryStream = new MemoryStream();
// MemoryStream에 넣을 byte 데이터
byte[] byArrData1 = BitConverter.GetBytes(1234); // 1234는 int
byte[] byArrData2 = BitConverter.GetBytes(5678); // 5678은 int
// MemoryStream에 byArrData1을 적재
memoryStream.Write(byArrData1, 0, byArrData1.Length);
// MemoryStream에 byArrData2을 적재
memoryStream.Write(byArrData2, 0, byArrData2.Length);
// 위치를 0으로 되돌려 보냄
memoryStream.Position = 0;
// 적재한 데이터를 다시 원래대로 넣을 배열
byte[] byArrOrgData1 = new byte[byArrData1.Length];
byte[] byArrOrgData2 = new byte[byArrData2.Length];
// 적재된 데이터에서 첫번째로 넣었던 데이터(1234)를 byArrOrgData1 배열에 적재
memoryStream.Read(byArrOrgData1, 0, byArrOrgData1.Length);
// 적재된 데이터에서 두번째로 넣었던 데이터(5678)를 byArrOrgData1 배열에 적재
memoryStream.Read(byArrOrgData2, 0, byArrOrgData2.Length);
// Byte 데이터를 int 데이터로 변환
int nOrgData1 = BitConverter.ToInt32(byArrOrgData1, 0);
int nOrgData2 = BitConverter.ToInt32(byArrOrgData2, 0);
// MemoryStream 닫기
memoryStream.Close();
먼저 memoryStream의 Position을 0으로 돌려 보낸 뒤에
데이터를 순차적으로 Byte 개수만큼 가져와서 넣어줄 Byte 배열에 넣습니다.
그리고 데이터를 BitConverter를 이용하여 원래대로 역직렬화를 하면 위와 같이 원래의 값을 가지고 온 것을 확인할 수 있습니다.
또한 Position은 역시 8을 가리킵니다.
StreamReader 와 StreamWriter
MemoryStream을 사용하여 직접적인 Byte 데이터가 아닌 문자열 데이터를 이용하고 싶다면 번거로운 작업을 수행해야합니다.
// MemoryStream
MemoryStream memoryStream = new MemoryStream();
// 문자열
byte[] buffer = System.Text.Encoding.UTF8.GetBytes("This is string");
memoryStream.Write(buffer, 0, buffer.Length);
// MemoryStream 닫기
memoryStream.Close();
Encoding을 사용하여 Byte로 변환하여야 합니다.
이 과정을 좀더 편하게 할 수 있게 해주는 것이 바로 "StreamReader" 와 "StreamWriter" 입니다.
위에서 본 예제를 다시 만들어보면
// MemoryStream
MemoryStream memoryStream = new MemoryStream();
// 데이터를 Memory에 쓰기
StreamWriter streamWriter = new StreamWriter(memoryStream, System.Text.Encoding.UTF8);
streamWriter.WriteLine("This is string");
// 내부 버퍼의 데이터를 Stream으로 전달
streamWriter.Flush();
// Position 위치 변경
memoryStream.Position = 0;
// 데이터를 Memory에서 읽기
StreamReader streamReader = new StreamReader(memoryStream, System.Text.Encoding.UTF8);
string strOrgData = streamReader.ReadToEnd();
// MemoryStream 닫기
memoryStream.Close();
이렇게 변하게 됩니다.
여기서 "Flush" 라는 함수가 나오게 되는데 StreamWriter의 경우에는 내부에 버퍼를 가지고 있는데 여기에 일정량의 데이터를 가지고 있다가 그 일정량을 채우면 Stream으로 데이터를 한꺼번에 보내게 됩니다.
이때 일정량을 채우지 않고도 Stream으로 데이터를 보내주는 기능을 "Flush" 함수가 수행을 해줍니다.
BinaryReader 와 BinaryWriter
말 그대로 Binary(이진) 데이터를 다룹니다.
// MemoryStream
MemoryStream memoryStream = new MemoryStream();
// 데이터를 Memory에 쓰기
BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
binaryWriter.Write($"This is string{Environment.NewLine}");
binaryWriter.Write(1234);
binaryWriter.Flush();
// Position 위치 변경
memoryStream.Position = 0;
// 데이터를 Memory에서 읽기
BinaryReader streamReader = new BinaryReader(memoryStream);
string strOne = streamReader.ReadString();
int nTwo = streamReader.ReadInt32();
// MemoryStream 닫기
memoryStream.Close();
예제를 보면 알겠지만 데이터를 넣은 순서대로 데이터를 다시 읽어올 때 형식에 맞게 다시 읽어오는 것을 알 수 있습니다.
StreamWriter 와 BinaryWriter 의 차이점
메모리를 보면 알 수 있습니다.
// MemoryStream
MemoryStream memoryStream = new MemoryStream();
// 데이터를 Memory에 쓰기
BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
binaryWriter.Write($"This is string{Environment.NewLine}");
binaryWriter.Write(1234);
binaryWriter.Flush();
// Position 위치 변경
memoryStream.Position = 0;
StreamWriter streamWriter = new StreamWriter(memoryStream, System.Text.Encoding.UTF8);
streamWriter.WriteLine("This is string");
streamWriter.Write(1234);
streamWriter.Flush();
// MemoryStream 닫기
memoryStream.Close();
Console.ReadLine();
위의 예제를 통해서 보도록 하겠습니다.
먼저 BinaryWriter의 경우
버퍼[0]는 첫번째 데이터의 문자 개수를 나타냅니다.
버퍼[1~16]에는 첫번째 데이터(This is string+개행(\r\n))를 나타냅니다.
버퍼[17~18]에는 두번째 데이터(1234)를 나타냅니다.
StreamWriter의 경우
버퍼[0~2]는 UTF-8의 BOM 문자를 나타냅니다.
버퍼[3~18]에는 첫번째 데이터(This is string+개행(\r\n))를 나타냅니다.
버퍼[19~20]에는 두번째 데이터(1234)를 문자열로 나타냅니다.
StreamWriter는 데이터를 문자열로 나타내어 쉽게 읽을 수 있으며
BinaryWriter는 규격이 정해진(순차적) 데이터를 빠르게 입출력 할 수 있습니다.
'Study > C#, Winform' 카테고리의 다른 글
[C#] DateTime 시간 자르기, 반올림, 반내림, 가까운 값 (1) | 2022.10.11 |
---|---|
[C#] Enumerable 에서 중복 데이터 삭제 (Distinct) (0) | 2022.10.06 |
[C# Winform] 스크롤바 크기 (넓이) (0) | 2022.10.04 |
[C# Winform] Context Menu를 Button 옆에 띄우기 (0) | 2022.09.28 |
[C#] 시간 관련 (DateTime, TimeSpan, Stopwatch) (0) | 2022.08.09 |