스트림은 파일과 메모리 간의 통로 역할을 하며, 특히 FileStream 클래스를 사용하면 디스크에 존재하는 파일에 접근하여 데이터를 읽거나 쓸 수 있습니다. 이 과정에서 비관리 리소스가 포함되므로 using 문을 통해 적절히 해제해야 합니다.
단일 바이트 단위로 읽기
ReadByte() 메서드는 파일에서 한 바이트씩 데이터를 읽어오며, 더 이상 읽을 데이터가 없을 경우 -1을 반환합니다. 이를 이용해 전체 파일을 순차적으로 출력할 수 있습니다.
using (FileStream fs = new FileStream("sample.txt", FileMode.Open, FileAccess.Read))
{
int data;
do
{
data = fs.ReadByte();
if (data != -1)
{
Console.Write((char)data);
}
} while (data != -1);
}
버퍼를 이용한 일괄 읽기
효율적인 처리를 위해 일정 크기의 바이트 배열을 버퍼로 사용하여 여러 바이트를 한 번에 읽을 수 있습니다. 이때 실제 읽은 바이트 수는 Read() 메서드의 반환값으로 확인할 수 있습니다.
using (FileStream fs = new FileStream("sample.txt", FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
{
string content = Encoding.Default.GetString(buffer, 0, bytesRead);
Console.WriteLine(content);
}
}
데이터 쓰기
파일에 데이터를 기록하려면 WriteByte() 또는 Write() 메서드를 사용합니다. 문자열이나 한글과 같은 유니코드 데이터는 인코딩 방식에 따라 변환 후 저장해야 올바르게 표현됩니다.
// 단일 바이트 쓰기
using (FileStream fs = new FileStream("output.txt", FileMode.Create))
{
fs.WriteByte(97); // 'a'
}
// 문자열 쓰기
using (FileStream fs = new FileStream("output.txt", FileMode.Create))
{
string text = "Hello World";
foreach (char c in text)
{
fs.WriteByte((byte)c);
}
}
// UTF-8 인코딩으로 한글 쓰기
using (FileStream fs = new FileStream("output.txt", FileMode.Create))
{
byte[] bytes = Encoding.UTF8.GetBytes("안녕하세요");
fs.Write(bytes, 0, bytes.Length);
}
파일 복사 구현
입력 스트림에서 데이터를 읽고 출력 스트림에 기록함으로써 파일 복사를 수행할 수 있습니다. 큰 파일의 경우 성능 향상을 위해 버퍼 크기를 조절할 수 있습니다.
using (FileStream source = new FileStream(@"source.mp4", FileMode.Open, FileAccess.Read))
using (FileStream target = new FileStream(@"target.mp4", FileMode.Create, FileAccess.Write))
{
byte[] buffer = new byte[1024 * 1024]; // 1MB 버퍼
int bytesRead;
while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0)
{
target.Write(buffer, 0, bytesRead);
}
}
복사 진행률 표시하기
전체 파일 크기와 현재까지 전송된 바이트 수를 비교하여 진행률을 계산하고 출력할 수 있습니다.
long totalBytes = source.Length;
long copiedBytes = 0;
int bytesRead;
while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0)
{
target.Write(buffer, 0, bytesRead);
copiedBytes += bytesRead;
double progress = (double)copiedBytes / totalBytes * 100;
Console.WriteLine($"진행률: {progress:F2}%");
}
StreamReader와 StreamWriter 사용
텍스트 기반 파일을 다룰 때는 StreamReader와 StreamWriter를 사용하면 더욱 편리합니다. 이들은 내부적으로 인코딩을 자동 처리해주며, 줄 단위 읽기나 전체 텍스트 읽기 등의 기능도 제공합니다.
using (FileStream fs = new FileStream("textfile.txt", FileMode.Open, FileAccess.Read))
using (StreamReader reader = new StreamReader(fs, Encoding.Default))
{
string content = reader.ReadToEnd();
Console.WriteLine(content);
}