8.8 QFile - Step 5
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. 패턴 정리
더보기
- 파일 쓰기 패턴
- file = QFile(path)
- file.open(QFile.WriteOnly | QFile.Text)
- stream = QTextStream(file)
- stream << "텍스트"
- file.close()
- 파일 읽기 패턴
- file = QFile(path)
- file.open(QFile.ReadOnly | QFile.Text)
- stream = QTextStream(file)
- content = stream.readAll()
- file.close()
- 파일 복사 패턴
- QFile.exists(src) / QFile.exists(dst)
- 필요 시 QFile.remove(dst) 로 기존 대상 삭제
- src_file = QFile(src)
- src_file.copy(dst)
- GUI와의 연결
- 파일 경로 입력 → QLineEdit
- 텍스트 입력/출력 → QTextEdit
- 파일 선택 → QFileDialog.getOpenFileName, getSaveFileName
- 사용자 피드백 → QMessageBox.information / warning / critical / question
5. 추가 과제
더보기
“원본 파일 찾기…” 버튼 추가
- QPushButton("원본 찾기") 만들어서
QFileDialog.getOpenFileName()로 선택한 경로를 line_src에 넣기
“대상 파일 찾기…” 버튼 추가
- getSaveFileName() 사용
- 선택한 경로를 line_dst에 자동으로 채워 넣기
읽은 내용을 다른 이름으로 저장하기
- [파일에서 읽기]로 불러온 뒤
[파일에 쓰기]로 다른 경로에 저장