728x90

1. 학습 목표

더보기

학습 로드맵:

  • Step 1 QFile.open() & QIODevice 플래그 이해하기
  • Step 2 콘솔에서 QFile 맛보기 (순수 Python 스크립트)
  • Step 3 PySide6 GUI 프로젝트 만들기 & 기본 창 띄우기
  • Step 4 GUI에서 “파일 쓰기/읽기” 버튼 구현
  •  Step 5 파일 복사 기능까지 확장

 

이 단계에서 목표는:

  • GUI에서 “파일 복사” 버튼을 눌렀을 때,
    원본 경로(line_src) → 대상 경로(line_dst)로 파일을 복사
  • QFile.exists() 로 원본/대상 존재 여부 확인
  • 대상 파일이 이미 있을 때, 덮어쓰기 여부를 묻는 대화상자 띄우기
  • QFile.copy() 의 동작 특성 이해
    (대상 파일이 이미 존재하면 실패하는 점 등)
  • 오류 상황별로 QMessageBox 로 사용자에게 친절하게 알리기

 

2. 복사 구현

더보기
def on_copy_clicked(self):
    """[파일 복사] 버튼: 원본 경로 → 대상 경로로 파일 복사"""

    src_path = self.line_src.text().strip()
    dst_path = self.line_dst.text().strip()

    # 1) 입력값 검증
    if not src_path:
        QMessageBox.warning(self, "경고", "원본 파일 경로를 입력하세요.")
        return

    if not dst_path:
        QMessageBox.warning(self, "경고", "복사 대상 파일 경로를 입력하세요.")
        return

    # 2) 원본 파일 존재 여부 확인
    if not QFile.exists(src_path):
        QMessageBox.critical(self, "오류", f"원본 파일이 존재하지 않습니다.\n경로: {src_path}")
        return

    # 3) 대상 파일이 이미 존재하는 경우, 덮어쓸지 확인
    if QFile.exists(dst_path):
        ret = QMessageBox.question(
            self,
            "파일 덮어쓰기 확인",
            f"대상 파일이 이미 존재합니다.\n덮어쓰시겠습니까?\n\n경로: {dst_path}",
            QMessageBox.Yes | QMessageBox.No,
            QMessageBox.No
        )

        if ret == QMessageBox.No:
            return

        # QFile.copy 는 대상이 이미 존재하면 실패하므로, 먼저 삭제
        if not QFile.remove(dst_path):
            QMessageBox.critical(
                self,
                "오류",
                f"기존 대상 파일을 삭제할 수 없습니다.\n경로: {dst_path}"
            )
            return

    # 4) 복사 실행
    src_file = QFile(src_path)

    if not src_file.copy(dst_path):
        QMessageBox.critical(
            self,
            "오류",
            f"파일 복사에 실패했습니다.\n원본: {src_path}\n대상: {dst_path}"
        )
    else:
        QMessageBox.information(
            self,
            "복사 완료",
            f"파일 복사가 완료되었습니다.\n원본: {src_path}\n대상: {dst_path}"
        )

 

3. on_copy_clicked() 동작 흐름

더보기

경로 입력값 검증

src_path = self.line_src.text().strip()
dst_path = self.line_dst.text().strip()

if not src_path:
    QMessageBox.warning(self, "경고", "원본 파일 경로를 입력하세요.")
    return

if not dst_path:
    QMessageBox.warning(self, "경고", "복사 대상 파일 경로를 입력하세요.")
    return

 

  • QLineEdit 두 개에서 문자열을 가져옵니다.
  • 공백만 있는 경우도 막기 위해 strip() 사용
  • 하나라도 비어 있으면 경고 메시지 후 함수 종료

 

 

 

 

원본 파일 존재 여부 확인

if not QFile.exists(src_path):
    QMessageBox.critical(self, "오류", f"원본 파일이 존재하지 않습니다.\n경로: {src_path}")
    return
  • QFile.exists(path)로 원본 파일이 실제로 존재하는지 확인
  • 없으면 더 이상 진행할 수 없으므로 에러 메시지 후 종료

 

 

 

 

대상 파일이 이미 있는 경우 처리

if QFile.exists(dst_path):
    ret = QMessageBox.question(
        self,
        "파일 덮어쓰기 확인",
        f"대상 파일이 이미 존재합니다.\n덮어쓰시겠습니까?\n\n경로: {dst_path}",
        QMessageBox.Yes | QMessageBox.No,
        QMessageBox.No
    )

    if ret == QMessageBox.No:
        return

    if not QFile.remove(dst_path):
        QMessageBox.critical(
            self,
            "오류",
            f"기존 대상 파일을 삭제할 수 없습니다.\n경로: {dst_path}"
        )
        return

 

  • QFile.copy()는 대상 파일이 이미 존재하면 보통 실패합니다.
  • 그래서 덮어쓰기 허용 여부를 먼저 물어보고,
    덮어쓰기로 결정하면 QFile.remove()로 대상 파일을 삭제한 뒤 복사합니다.
  • 삭제에 실패하면 복사를 진행할 수 없으므로 에러 처리 후 종료합니다.

 

 

 

 

QFile.copy()로 실제 복사 수행

src_file = QFile(src_path)

if not src_file.copy(dst_path):
    QMessageBox.critical(
        self,
        "오류",
        f"파일 복사에 실패했습니다.\n원본: {src_path}\n대상: {dst_path}"
    )
else:
    QMessageBox.information(
        self,
        "복사 완료",
        f"파일 복사가 완료되었습니다.\n원본: {src_path}\n대상: {dst_path}"
    )
  • src_file.copy(dst_path)
    → 성공 시 True, 실패 시 False
  • 실패하면 QMessageBox.critical()로 에러 표시
  • 성공하면 QMessageBox.information()로 복사 완료 안내

 

 

4. 패턴 정리

더보기
  1. 파일 쓰기 패턴
    • file = QFile(path)
    • file.open(QFile.WriteOnly | QFile.Text)
    • stream = QTextStream(file)
    • stream << "텍스트"
    • file.close()
  2. 파일 읽기 패턴
    • file = QFile(path)
    • file.open(QFile.ReadOnly | QFile.Text)
    • stream = QTextStream(file)
    • content = stream.readAll()
    • file.close()
  3. 파일 복사 패턴
    • QFile.exists(src) / QFile.exists(dst)
    • 필요 시 QFile.remove(dst) 로 기존 대상 삭제
    • src_file = QFile(src)
    • src_file.copy(dst)
  4. GUI와의 연결
    • 파일 경로 입력 → QLineEdit
    • 텍스트 입력/출력 → QTextEdit
    • 파일 선택 → QFileDialog.getOpenFileName, getSaveFileName
    • 사용자 피드백 → QMessageBox.information / warning / critical / question

 

5. 추가 과제

더보기

“원본 파일 찾기…” 버튼 추가

  • QPushButton("원본 찾기") 만들어서
    QFileDialog.getOpenFileName()로 선택한 경로를 line_src에 넣기

 

“대상 파일 찾기…” 버튼 추가

  • getSaveFileName() 사용
  • 선택한 경로를 line_dst에 자동으로 채워 넣기

 

읽은 내용을 다른 이름으로 저장하기

  • [파일에서 읽기]로 불러온 뒤
    [파일에 쓰기]로 다른 경로에 저장