대량의 파일을 이동하거나 또는 다른 이름으로 변경하여 파일을 복사해야할 때가 있다.
나 같은 경우는 회사에서 요구하는 파일 이동 작업이 조건 별로 이루어 질 때 약 10만 개 이상의 파일을 선별 및 추출해야하는 데,
이런 경우 일일이 수작업을 하게 되면 시간이 매우 오래 걸린다.
차라리 직접 파일 선별 및 추출 작업을 하는 것보다 시간이 조금 걸리더라도
프로그램을 만들어서 작업을 수행하는 것이 결과론적으로 시간을 획기적으로 줄일 수 있다.
또한, 한 번 만들어 놓으면 다음 관련 작업은 클릭 한 번에 끝나게 되니 나중을 위해서도 효율적이다.

이번 글에서는 C# 프로그래밍을 통해 WInform을 이용한 윈도우 프로그램으로 파일 관련 처리 방법을 다룬다.

이 글에 사용된 예제 프로젝트 다운로드하기

샘플로 사용된 파일 관리 프로젝트는 깃허브에 공유되어 있다.
다른 예제들도 있으니 도움이 되길 바란다.
> luvris2 – C# 예제 프로젝트 깃허브 바로가기

해당 예제가 포함된 링크로 바로 가기
> C#_Winform_File_Management_Example

파일 및 디렉토리를 처리하기 위한 준비물 (System.IO)

파일을 프로그래밍으로 다루려면 어떻게 해야할까?
그러기 위해서는 System.IO 라는 네임스페이스가 필요하다.

System.IO 네임스페이스는 파일 생성, 복사, 이동, 삭제부터 디렉토리 생성, 삭제, 검색까지
파일 시스템과 상호 작용하는 데 필요한 다양한 클래스와 메서드를 제공한다.
쉽게 말하자면, 이 네임스페이스를 이용하여 컴퓨터 속 파일 탐색기를 코드로 제어하는 것과 같다.

프로젝트 최상단 코드에 System.IO 네임스페이스를 사용할 수 있도록 코드를 추가해준다.

using System.IO;
C#

System.IO의 자주 사용되는 클래스 알아보기

System.IO 네임스페이스에서 가장 자주 사용되는 클래스들을 알아보자.
이 클래스들을 활용하면 파일과 디렉토리를 관리하는 데 매우 유용하다.

File 클래스

파일을 생성, 복사, 이동, 삭제하고, 파일 속성을 읽고 설정하는 정적 메서드를 제공한다.

  • File.Copy(“원본파일”, “복사파일”, “덮어쓰기여부”)
    • 덮어쓰기 여부 옵션을 정할 수 있다.
    • true일 경우, 파일이 존재하면 복사할 파일로 덮어쓰기를 한다.
    • false일 경우에는 파일이 존재하면 복사를 진행하지 않으며 System.IO.IOException 오류가 발생한다.
      오류 내용 : System.IO.IOException: '파일이 이미 있으므로 만들 수 없습니다.'
  • File.Move(“원본파일”, “복사파일”, “덮어쓰기여부”)
    • 덮어쓰기 여부 옵션을 정할 수 있다.
    • File.Copy 메서드와 동일하다.
// 새 파일 생성하기
File.Create("새파일.txt"); // 새파일.txt 생성

// 파일 복사하기
File.Copy("원본파일.txt", "복사본.txt");

// 파일 이동하기
File.Move("원본파일.txt", "복사본.txt");

// 파일 삭제하기
File.Delete("삭제할파일.txt");
C#

FileInfo 클래스

특정 파일에 대한 인스턴스를 생성하여 파일 크기, 생성 시간 등 정보 확인 등 파일 작업을 수행한다.

// 파일.txt에 대한 인스턴스 생성
FileInfo fileInfo = new FileInfo("파일.txt");

// 파일 크기 가져오기
long fileSize = fileInfo.Length;

// 생성 시간 가져오기
DateTime creationTime = fileInfo.CreationTime;
C#

Directory 클래스

디렉토리 생성, 삭제, 이동, 현재 디렉토리 정보 가져오는 정적 메서드를 제공한다.

// 새폴더 생성하기
Directory.CreateDirectory("새폴더");

// 폴더 삭제하기
Directory.Delete("삭제할폴더");

// 현재 디렉토리 경로 가져오기
string currentDirectory = Directory.GetCurrentDirectory();

// 조건을 충족하는 하위 디렉토리 경로 가져오기
var subDirectories = Directory.GetDirectories("폴더경로", "검색패턴", "검색옵션");
C#

GetDirectories 부연 설명

  • 검색 패턴 : String 형태로 입력, ‘폴더경로’에 있는 하위 디렉터리 이름과 일치하는지 비교할 검색 문자열이다. 이 매개 변수는 유효한 리터럴 및 와일드카드 문자로 된 조합을 포함하지만 정규식을 지원하지 않는다.
  • 검색 옵션 : 검색 작업에 현재 디렉터리만 포함할지 아니면 모든 하위 디렉터리를 포함할지를 지정하는 열거형 값 중 하나를 입력한다.

DirectoryInfo 클래스

특정 디렉토리에 대한 인스턴스 생성하여 하위 디렉토리 및 파일 정보를 탐색한다.

// 특정 폴더에 대한 인스턴스 생성
DirectoryInfo directoryInfo = new DirectoryInfo("폴더");

// 하위 디렉토리 정보 가져오기
DirectoryInfo[] subdirectories = directoryInfo.GetDirectories();

// 폴더 내 파일 정보 가져오기
FileInfo[] files = directoryInfo.GetFiles();
C#

Path 클래스

파일 및 디렉토리 경로 조작, 파일 확장자, 파일명, 디렉토리명 추출한다.

// 파일명 추출 : 파일.txt
string fileName = Path.GetFileName("C:/폴더/파일.txt");

// 파일 확장자 추출 : .txt
string extension = Path.GetExtension("C:/폴더/파일.txt");

// 파일 경로 추출 : C:/폴더
string directoryPath = Path.GetDirectoryName("C:/폴더/파일.txt");
C#

✅ 알아두면 유용한 추가 지식
C# 프로젝트의 현재 경로를 반환하는 코드는 Environment.CurrentDirectory이다.

// 현재 C# 프로젝트의 경로 구하기 : C:\C#_Winform_File_Management_Example\bin\Debug\net8.0-windows
var projectPath = Environment.CurrentDirectory;
C#

텍스트 문서 파일을 읽고 쓰려면? StreamReader/StreamWriter

예를 들어, 설정 파일을 읽어오거나 로그 파일을 기록해야 할 때가 있다.
단순히 파일을 이동, 복사, 저장이 아닌 직접 읽어서 써야한다.
이럴 때 유용하게 사용할 수 있는 기능이 StreamReader StreamWriter 이다.

StreamReader&StreamWriter가 뭘까?

스트림 리더 및 스트림 라이터는 닷넷 프레임워크(.NET Framework)에서 제공하는 클래스로 텍스트 파일을 읽고 쓰는 데 사용된다.
스트림 리더를 사용하면 파일에서 한 번에 한 줄씩 또는 전체 내용을 한 번에 읽어 올 수 있다.
스트림 라이터를 사용하면 파일에 내용을 추가하거나 덮어쓸 수 있다.

간단히 말해서 StreamReader는 텍스트 파일을 읽기 쉽게 만들어주는 도구로,
StreamWriter는 텍스트 파일을 쉽게 저장하는 도구로 생각하면 된다.

스트림 리더로 텍스트 파일 읽기

먼저, StreamReader 객체를 생성하고 읽을 파일의 경로를 지정해야 한다.
그리고 ReadLine() 메서드를 사용하여 파일에서 한 줄씩 읽어온다.
파일 읽기가 끝나면 Close() 메서드를 사용하여 StreamReader 객체를 닫는다.

  • ReadLine() 메서드
    • 파일에서 한 줄을 읽어와 문자열로 반환하는 메서드
    • 파일의 끝에 도달하면 null 값 반환
// 읽어올 파일 경로 지정
string filePath = "C:\\example.txt"; 

// 스트림 리더 객체 생성
StreamReader reader = new StreamReader(filePath);

// 파일 읽기
string line;
while ((line = reader.ReadLine()) != null)
{
    Console.WriteLine(line); // 읽은 내용 콘솔에 출력
}

// 스트림 리더 객체 닫기
reader.Close();
C#

스트림 라이터로 텍스트 파일 쓰기

StreamReader는 파일 읽기 전용 도구이다. 텍스트 파일을 쓰려면 StreamWriter 클래스를 사용해야 한다.
StreamWriter 사용법은 StreamReader와 매우 유사하다.

먼저, StreamWriter 객체를 생성하고 쓸 파일의 경로를 지정한다.
* 두 번째 매개변수true 일 경우에는 파일에 내용을 추가하며, false 일 경우에는 파일의 내용을 덮어쓴다.
그리고 WriteLine() 메서드를 사용하여 파일에 텍스트를 저장한다.
파일 쓰기가 끝나면 Close() 메서드를 사용하여 StreamWriter 객체를 닫는다.

  • WriteLine() 메서드
    • 파일에 텍스트를 쓰는 메서드
    • 두 번째 매개변수를 지정할 경우, 파일이 없으면 새 파일을 만든다.
// 읽어올 파일 경로 지정
string filePath = "C:\\example.txt"; 

// 스트림 라이터 객체 생성, true 옵션은 파일에 내용을 추가하겠다는 의미
StreamWriter writer = new StreamWriter(filePath, true);

// 파일 쓰기
writer.WriteLine("새로운 내용 추가");

// 스트림 라이터 객체 닫기
writer.Close();
C#

파일 다루기 예제: 텍스트 파일을 읽고 쓰고, 복사, 이동, 삭제를 해보자!

간단히 예제를 구성하기 위해 프로젝트를 최대한 간편히 만들어보았다.
파일은 깃 허브에서 다운로드 받아서 재현해볼 수 있도록 기본 경로는 프로젝트 실행 폴더를 기준으로 하였다.
만약, 절대 경로로 모든 경로에 대해 파일을 다루고자 한다면
샘플 예제 코드에서 변수 basePath 부분을 빼고 경로를 입력하는 텍스트 박스에 경로와 함께 파일 이름을 기재해주면 된다.
또한, 샘플 예제는 파일 복사, 이동 시 덮어쓰기를 하여 파일 처리를 수행하는 것임을 알아두자.

요구사항

  1. 텍스트 파일(.txt)을 호출할 수 있어야 한다.
    • 텍스트 파일을 불러 올 수 있도록 경로를 기입하는 란이 있어야 한다.
  2. 텍스트 파일을 편집할 수 있어야 한다.
  3. 수정된 텍스트 파일을 저장할 수 있어야 한다.
  4. 텍스트 파일을 새 경로에 파일을 복사할 수 있어야 한다.
    • 새 경로로 파일을 복사 할 수 있도록 새 경로를 기입하는 란이 있어야 한다.
  5. 텍스트 파일을 새 경로로 파일을 이동할 수 있어야 한다.
    • 위 조건과 동일함.
  6. 텍스트 파일을 삭제할 수 있어야 한다.

UI 설계

C# 프로그래밍 언어를 이용하여 파일 불러오기, 저장, 복사, 이동, 삭제 기능을 수행하는 윈도우 프로그램 예제 이미지
  • 파일 경로 입력란 (TextBox)
    • Name : txtOriginPath
  • 새 경로 입력란 (TextBox)
    • Name : txtNewPath
  • 파일 불러오기 버튼 (Button)
    • Name : btnRead
    • Text : 파일 불러오기
  • 파일 저장하기 버튼 (Button)
    • Name : btnSave
    • Text : 파일 저장하기
  • 새 경로에 파일 복사 버튼 (Button)
    • Name : btnCopy
    • Text : 새 경로에 파일 복사
  • 새 경로로 파일 이동 버튼 (Button)
    • Name : btnMove
    • Text : 새 경로로 파일 이동
  • 파일 삭제하기 버튼 (Button)
    • Name : btnDelete
    • Text : 파일 삭제하기
  • 불러온 텍스트 문서를 표시할 텍스트박스 (TextBox)
    • Name : txtContent
    • Multiline : True
    • ScrollBars : Vertical
    • [참고] 텍스트 문서를 불러올 때 스크롤 바와 여러 줄을 표현할 수 있어야 하므로 속성 값을 변경함.

코딩

기본 경로 저장 변수 선언

// 기본 경로 : 프로젝트 실행 경로를 기준으로 함
string basePath = Environment.CurrentDirectory;
C#

파일 경로와 이름을 가져오는 메서드

  • getFilePath() : 읽고 쓰거나 삭제할 파일의 경로와 파일 이름을 추출하는 메서드
  • getNewFilePath() : 파일을 이동, 복사할 파일의 경로와 파일 이름을 추출하는 메서드
        // 입력한 파일 이름 가져오기
        private string getFilePath()
        {
            return basePath + "\\" + txtOriginPath.Text;
        }

        // 입력한 새로운 파일 이름 가져오기
        private string getNewFilePath()
        {
            return basePath + "\\" + txtNewPath.Text;
        }
C#

파일 디렉토리 유효성 확인 및 디렉토리 생성 메서드

  • checkDirectory(string path) : 파일의 경로가 존재하는지 확인하고, 경로가 존재하지 않으면 디렉토리를 생성하는 메서드. 디렉토리가 존재하지 않을 경우, 오류를 반환하기 때문에 경로를 만들어줘야 한다.
// 파일 경로 유효성 확인하기
private void checkDirectory(string path)
{
    // 디렉토리 경로만 추출
    string directoryPath = Path.GetDirectoryName(path);

    // 경로가 존재하지 않으면 디렉토리 생성
    if (!Directory.Exists(directoryPath))
    {
        Directory.CreateDirectory(directoryPath);
    }
}
C#

파일 불러오기 버튼

  • btnRead_Click : 파일 불러오기 버튼의 클릭 이벤트 리스너, StreamReader 를 사용하여 파일의 내용을 읽어온다.
// 파일 불러오기
private void btnRead_Click(object sender, EventArgs e)
{
    // 텍스트를 표시할 텍스트박스 초기화
    txtContent.Text = "";

    // 불러올 파일 경로 확인
    string filePath = getFilePath();

    // 파일 경로 유효성 확인
    if (File.Exists(filePath))
    {
        using (StreamReader reader = new StreamReader(filePath))
        {
            // 파일 읽기
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                txtContent.Text += line + Environment.NewLine; // 줄의 마지막이면 다음 줄로 이동
            }
        }
    }
}
C#

파일 저장하기 버튼

  • btnSave_Click : 파일 저장하기 버튼 이벤트 리스너, StreamWriter 를 사용하여 파일의 내용을 덮어쓴다.
// 파일 저장하기
private void btnSave_Click(object sender, EventArgs e)
{
    // 저장할 파일 경로 확인
    string FilePath = getFilePath();

    // 저장할 파일 내용
    string content = txtContent.Text;

    // 파일 쓰기 : false (덮어쓰기)
    using (StreamWriter writer = new StreamWriter(FilePath, false))
    {
        writer.WriteLine(content);
    }
}
C#

새 경로에 파일 복사하기 버튼

  • btnCopy_Click : 새 경로에 파일 복사하기 버튼 이벤트 리스너, File.Copy 를 사용하여 파일을 복사한다.
// 새 경로에 파일 복사하기
private void btnCopy_Click(object sender, EventArgs e)
{
    // 파일 경로 확인
    string filePath = getFilePath();

    // 새 파일 경로 확인
    string newFilePath = getNewFilePath();

    // 파일 경로 확인, 없으면 디렉토리 생성
    checkDirectory(newFilePath);

    // 파일 복사
    File.Copy(filePath, newFilePath, true);
}
C#

새 경로로 파일 이동하기 버튼

  • btnMove_Click : 새 경로로 파일 이동하기 버튼 이벤트 리스너, File.Move 를 사용하여 파일을 이동한다.
// 새 경로로 파일 이동하기
private void btnMove_Click(object sender, EventArgs e)
{
    // 파일 경로 확인
    string filePath = getFilePath();

    // 새 파일 경로 확인
    string newFilePath = getNewFilePath();

    // 파일 경로 확인, 없으면 디렉토리 생성
    checkDirectory(newFilePath);

    // 파일 이동
    File.Move(filePath, newFilePath, true);
}
C#

파일 삭제하기 버튼

  • btnDelete_Click : 파일 삭제하기 버튼 이벤트 리스너, File.Delete 를 용하여 파일을 삭제한다.
// 파일 삭제하기
private void btnDelete_Click(object sender, EventArgs e)
{
    // 파일 경로 확인
    string filePath = getFilePath();

    // 파일 삭제
    File.Delete(filePath);
}
C#

테스트

기초 데이터 및 파일

파일을 다루기 위해 프로젝트 실행 경로에 테스트 파일(test1.txt)을 생성하였다. 내용은 다음과 같다.
깃 허브에서는 프로젝트 파일만 올라가기 때문에 다운로드 받은 프로젝트의 test1.txt 파일을
자신의 프로젝트 실행 경로로 이동해주어야 한다.

  • 경로 : 프로젝트 실행 경로/test1.txt (\bin\Debug\net8.0-windows)
  • 내용 : 테스트 파일입니다.
파일 처리 테스트를 위한 텍스트 문서 생성

파일 불러오기

  1. 파일 경로 입력 : test1.txt
  2. 파일 불러오기 버튼을 클릭하여 텍스트 문서 파일이 불러와지는지 확인
파일 불러오기 테스트 이미지

파일 저장 후 다시 불러오기

  1. 파일 경로 입력 : test1.txt
  2. 파일 불러오기 버튼 클릭
  3. 파일의 내용이 불러와져 있는 텍스트 박스에 파일 내용 수정
  4. 파일 저장하기 버튼 클릭
  5. 파일 불러오기 버튼을 클릭하여 저장한 내용을 다시 불러오는지 확인
파일 저장하기 테스트 이미지

새 경로에 파일 복사

  1. 파일 경로 입력 : test1.txt
  2. 새 경로 입력 : subDir/test2.txt
  3. 새 경로에 파일 복사 버튼을 눌러 파일이 복사되었는지 확인
파일 복사하기 테스트 이미지

새 경로로 파일 이동

  1. 파일 경로 입력 : test1.txt
  2. 새 경로 입력 : test3.txt
  3. 새 경로로 파일 이동 버튼을 눌러 파일이 이동되었는지 확인
파일 이동하기 테스트 이미지

파일 삭제하기

  1. 파일 경로 입력 : test3.txt
  2. 파일 삭제하기 버튼을 눌러 파일이 삭제되었는지 확인
파일 삭제하기 테스트 이미지

유의사항

경로를 기재할 때에는 반드시 이스케이프 문자를 사용하여 경로를 표시해주어야 한다.

참고된 자료

마이크로소프트 공식 문서 – System.IO 네임스페이스

Similar Posts

댓글 남기기