C# 스트림(Stream)이란?
파일(File)은 특정 이름과 디렉터리 경로를 가지며 디스크에 저장된 데이터의 집합입니다. 이러한 파일을 읽기 또는 쓰기 위해 열게 되면, 프로그램과 파일 사이의 데이터 흐름인 스트림(Stream)이 생성됩니다.
스트림의 종류
- 바이트 스트림(Byte Streams):
Stream,FileStream,MemoryStream,BufferedStream등이 포함됩니다. - 문자 스트림(Character Streams):
TextReader-TextWriter,StreamReader,StreamWriter및 기타 문자 기반 스트림이 포함됩니다.
바이트 스트림은 스트림 내부의 데이터를 바이트(byte) 단위로 처리하는 클래스들로 구성됩니다. 텍스트뿐 아니라 이미지, 동영상 같은 이진(binary) 데이터를 다룰 때 적합합니다.
Stream 클래스의 주요 속성
System.IO.Stream 추상 클래스는 모든 바이트 스트림 클래스의 기반이 됩니다. 대표적인 속성은 다음과 같습니다.
- CanRead — 현재 스트림이 읽기를 지원하는지 여부
- CanWrite — 현재 스트림이 쓰기를 지원하는지 여부
- Length — 스트림의 전체 길이(바이트 수)
System.IO 네임스페이스
System.IO 네임스페이스에는 파일 생성·삭제, 파일 읽기·쓰기, 파일 닫기 등 다양한 파일 입출력 작업을 수행하는 여러 클래스들이 포함되어 있습니다.
앞서 살펴본 스트림 관련 입출력(I/O) 클래스들을 아래 표로 정리했습니다.
| 번호 | I/O 클래스 및 설명 |
|---|---|
| 1 | BinaryReader 이진 스트림에서 기본(primitive) 데이터 형식을 읽습니다. |
| 2 | BinaryWriter 기본 데이터 형식을 이진 형식으로 씁니다. |
| 3 | BufferedStream 바이트 스트림을 위한 임시 저장소(버퍼) 역할을 합니다. |
| 4 | Directory 디렉터리 구조를 조작하는 정적 메서드를 제공합니다. |
| 5 | DirectoryInfo 디렉터리에 대한 다양한 작업을 수행하는 인스턴스 클래스입니다. |
| 6 | DriveInfo 드라이브에 대한 정보를 제공합니다. |
| 7 | File 파일 조작을 위한 정적 메서드를 제공합니다. |
| 8 | FileInfo 파일에 대한 다양한 작업을 수행하는 인스턴스 클래스입니다. |
| 9 | FileStream 파일 내 임의 위치에서 읽고 쓰는 데 사용됩니다. |
| 10 | MemoryStream 메모리에 저장된 스트림 데이터에 임의 접근(random access)할 때 사용됩니다. |
| 11 | Path 파일 경로 정보에 대한 작업을 수행합니다. |
| 12 | StreamReader 바이트 스트림에서 문자를 읽어 들이는 데 사용됩니다. |
| 13 | StreamWriter 스트림에 문자를 쓰는 데 사용됩니다. |
| 14 | StringReader 문자열 버퍼에서 데이터를 읽는 데 사용됩니다. |
| 15 | StringWriter 문자열 버퍼에 데이터를 쓰는 데 사용됩니다. |
FileStream 활용 예제
다음은 FileStream을 사용해 파일에 바이트를 쓰고 다시 읽어 오는 간단한 예제입니다.
using System;
using System.IO;
using System.Text;
class Program
{
static void Main()
{
string path = "sample.bin";
// 파일에 바이트 쓰기
byte[] data = Encoding.UTF8.GetBytes("Hello, C#");
using (FileStream fs = new FileStream(path, FileMode.Create))
{
fs.Write(data, 0, data.Length);
}
// 파일에서 바이트 읽기
using (FileStream fs = new FileStream(path, FileMode.Open))
{
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
Console.WriteLine(Encoding.UTF8.GetString(buffer)); // "Hello, C#" 출력
}
}
}위 예제처럼 스트림 객체는 반드시 using 문 또는 Dispose() 호출을 통해 사용 후 해제해야 리소스 누수를 방지할 수 있습니다. 또한 BufferedStream을 함께 사용하면 작은 단위의 입출력을 버퍼에 모았다가 한 번에 처리하여 성능을 크게 향상시킬 수 있습니다.