비동기 파일 입출력
비동기 파일 입출력은 파일을 읽고 쓰는 작업을 비동기적으로 수행하는 것을 의미한다. 즉, 파일 작업이 완료될 때까지 기다리지 않고 다른 작업을 계속 수행할 수 있다.
이는 UI 응답성을 유지하거나 CPU를 효율적으로 사용하는 데 유용하다.
C#에서는 async와 await 키워드를 사용하여 비동기 파일 입출력을 쉽게 구현할 수 있다. FileStream 클래스는 비동기 파일 입출력을 위한 ReadAsync() 메서드와 WriteAsync() 메서드를 제공한다.
ReadAsync() 메서드
Task<int> 객체를 반환한다. Task<int> 객체는 비동기 작업의 결과를 나타내며, Result 프로퍼티를 통해 읽어온 바이트 수를 가져올 수 있다.WriteAsync() 메서드
Task 객체를 반환한다. Task 객체는 비동기 작업을 나타내며, Wait() 메서드를 사용하여 작업이 완료될 때까지 기다릴 수 있다.예시
using (FileStream fileStream = new FileStream("file.txt", FileMode.Open))
{
byte[] buffer = new byte[1024];
int bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length);
// ...
}
이 코드는 file.txt 파일에서 1024 바이트를 비동기적으로 읽어온다. await 키워드는 ReadAsync() 메서드가 완료될 때까지 기다린다.
예제 코드
using System; // 기본적인 C# 기능을 사용하기 위해 필요한 네임스페이스
using System.IO; // 파일 입출력을 위한 FileStream 클래스를 사용하기 위해 필요한 네임스페이스
using System.Threading.Tasks; // 비동기 작업을 위한 Task 클래스를 사용하기 위해 필요한 네임스페이스
namespace AsyncFileIO // AsyncFileIO라는 이름의 네임스페이스를 정의한다
{
class MainApp // MainApp이라는 이름의 클래스를 정의한다
{
// 파일 복사 후 복사한 파일 용량을 반환하는 비동기 메서드이다.
static async Task<long> CopyAsync(string FromPath, string ToPath)
{
using (var fromStream = new FileStream(FromPath, FileMode.Open)) // FromPath 경로의 파일을 읽기 모드로 연다. using 구문을 사용하여 스트림을 자동으로 닫는다.
{
long totalCopied = 0; // 복사된 바이트 수를 저장할 변수를 0으로 초기화한다.
using (var toStream = new FileStream(ToPath, FileMode.Create)) // ToPath 경로의 파일을 쓰기 모드로 연다. 만약 파일이 없으면 새로 생성한다. using 구문을 사용하여 스트림을 자동으로 닫는다.
{
byte[] buffer = new byte[1024]; // 1024 바이트 크기의 버퍼를 생성한다. 파일 데이터를 버퍼 단위로 읽고 쓴다.
int nRead = 0; // 읽어온 바이트 수를 저장할 변수를 선언한다.
// fromStream에서 데이터를 읽어와 toStream에 쓸 때까지 반복한다.
while ((nRead = await fromStream.ReadAsync(buffer, 0, buffer.Length)) != 0) // fromStream에서 buffer 크기만큼 데이터를 비동기적으로 읽어온다. 읽어온 바이트 수를 nRead에 저장한다.
{
await toStream.WriteAsync(buffer, 0, nRead); // toStream에 buffer의 내용을 비동기적으로 쓴다.
totalCopied += nRead; // 복사된 바이트 수를 누적한다.
}
} // toStream을 닫는다.
return totalCopied; // 복사된 바이트 수를 반환한다.
} // fromStream을 닫는다.
}
static async void DoCopy(string FromPath, string ToPath) // 파일 복사를 수행하는 비동기 메서드이다.
{
long totalCopied = await CopyAsync(FromPath, ToPath); // CopyAsync 메서드를 호출하여 파일을 복사하고, 복사된 바이트 수를 totalCopied에 저장한다.
Console.WriteLine($"Copied Total {totalCopied} Bytes."); // 복사된 바이트 수를 출력한다.
}
static void Main(string[] args) // 프로그램의 진입점이다.
{
if (args.Length < 2) // 명령줄 인수가 2개 미만이면
{
Console.WriteLine("Usage : AsyncFileIO <Source> <Destination>"); // 사용법을 출력하고
return; // 프로그램을 종료한다.
}
DoCopy(args[0], args[1]); // DoCopy 메서드를 호출하여 파일을 복사한다.
Console.ReadLine(); // 사용자 입력을 기다린다.
}
}
}
코드 설명
이 C# 코드는 비동기 파일 입출력을 사용하여 파일을 복사하는 프로그램이다.
CopyAsync 메서드는 FileStream과 async/await 키워드를 사용하여 파일을 비동기적으로 복사하고, DoCopy 메서드는 CopyAsync 메서드를 호출하여 파일 복사를 수행한다. Main 메서드는 명령줄 인수를 확인하고 DoCopy 메서드를 호출한다.
async/await 키워드
async 키워드는 메서드가 비동기적으로 실행될 수 있음을 나타낸다.await 키워드는 비동기 작업이 완료될 때까지 메서드의 실행을 일시 중지한다.FileStream 클래스
FileStream 클래스는 파일을 읽고 쓰는 데 사용된다.FileMode.Open: 기존 파일을 연다.FileMode.Create: 새 파일을 생성한다. 파일이 이미 있으면 덮어쓴다.ReadAsync 메서드
ReadAsync 메서드는 파일에서 데이터를 비동기적으로 읽는다.WriteAsync 메서드
WriteAsync 메서드는 파일에 데이터를 비동기적으로 쓴다.출력 결과
Copied Total {파일 크기} Bytes.
오류 발생
출력 결과 다음과 같은 메시지가 콘솔에 표시된다.
Usage : AsyncFileIO <Source> <Destination>
해결 방법
Usage : AsyncFileIO <Source> <Destination> 이 출력 결과는 사용자가 프로그램 실행 시 필요한 명령줄 인수를 입력하지 않았을 때 나타나는 메시지이다. 즉, 프로그램을 실행하려면 <Source>와 <Destination>에 해당하는 파일 경로를 입력해야 한다.
예를 들어, "source.txt" 파일을 "destination.txt" 파일로 복사하려면 다음과 같이 명령줄에 입력해야 한다.
AsyncFileIO source.txt destination.txt
