파일 입출력 stream

프로그램 실행 중에 메모리에저장된 데이터는 프로그램이 종료되면 사란진다. 따라서 데이터를 프로그램이 종료된 이후에도 사용하려면 파일로 저장하고 필요할 때마다 파일을 읽어서 데이터를 사용해야 한다.

with 문

-파일, 네트워크 연결, 데이터베이스 연결 등 리소스를 사용한 작업이 끝난 후에 이를 자동으로 정리(cleanup)
-파일을 열고 작업한 후 파일을 자동으로 닫거나, 잠금을 해제하는 등의 처리를 보장
-작업 중 예외가 발생하더라도 자동으로 리소스를 정리하므로, 예외로 인해 리소스가 닫히지 않는 문제를 방지

수동닫기와 자동닫기

-파일을 open()을 이용하여 열고 작업이 끝나면 close()를 이용하여 파일을 닫아줘야 한다.
-with문을 사용하면 파일을 알아서 정리해주기 때문에 작업 효율이 향상된다.

<수동닫기와 자동닫기 예시 코드>

#수동 닫기
file = open('eaxmple.txt', 'w') #파일 열기
file.write('hello, Python!') #파일에 쓰기
file.close() #파일 닫기

#자동 닫기
with open('example.txt', 'w') as file: 
	file.write('hello, Pyrhon!') #파일에 쓰기
#파일은 자동으로 닫힘

파일 입출력

파일객체 = open(파일명, 파일 모드)

<파일 모드 종류>
r: 읽기 모드 (파일이 존재해야 함)
w: 쓰기 모드 (파일이 없으면 새로 생성, 기존 파일 내용 삭제)
a: 추가 모드 (기존 파일 끝에 내용 추가)
b: 바이너리 데이터 (영상, 이미지, 소리 등)

파일 쓰기

-write() 메서드 사용.
-문자열만 입력 가능하므로 숫자는 문자열 형태로 변환 후 사용.
-한글 깨짐을 방지하기 위해 open() 메서드의 3번째 인자로 encoding = 'utf-8' 입력

<write() 메서드 활용 코드 예시>

#파일 입출력
#파일 쓰기
with open("test.txt", "w", encoding="utf-8") as file: #쓰기 모드
    file.write("안녕하세요\n")
    file.write("파이썬 쓰기 연습중입니다. \n") #파일 자동으로 닫힘
print("파일에 데이터가 작성되었습니다.")


# 파일 추가
with open("test.txt", "a", encoding="utf-8") as file:
    file.write("내용 추가\n")
print("파일에 데이터가 추가되었습니다.")

<test.txt에 저장된 텍스트>
안녕하세요
파이썬 쓰기 연습중입니다.
내용 추가

-writelines() 메서드를 사용하여 문자열 리스트를 텍스트로 입력할 수도 있다.

<writelines() 메서드 활용 코드 예시>

lines = ["첫번째\n", "두번째\n", "세번째\n"] #문자열 리스트

with open("test2.txt", "w", encoding="utf-8") as file:
    file.writelines(lines)

<test2.txt에 저장된 텍스트>
첫번째
두번째
세번째

-사용자로부터 입력 받아 텍스트 파일을 작성하는 것도 가능하다.
<사용자 입력을 받아 텍스트 파일 작성하기 코드 예시>

with open("user.txt", "w", encoding="utf-8") as file:
    while True: #무한 반복
        line = input("파일에 넣을 문자열 입력(종료하려면 '종료'입력): ")
        if line == "종료": 
            print("입력을 종료합니다")
            break #종료 조건 블럭
        file.write(line + "\n") #input 한 번 끝날 때마다 줄 바꾸기

파일 읽기

<파일 읽기 모드의 메서드>
-read(): 파일의 내용 전체를 문자열로 반환 -> 이 3개의 메서드 중 메모리 사용량이 높다!
-readline(): 파일에서 한 줄만 읽어온다. -> 메모리 사용량이 적다.
-readlines(): 파일의 모든 줄을 읽고, 각각의 줄을 요소로 갖는 리스트를 반환 -> 메모리 사용량이 보통이다.

e.g.)
큰 파일 -> readline()을 사용하여 한 줄씩 처리
작은 파일 -> read() 또는 readlines()을 사용하여 빠르게 처리

-파일 쓰기할 때 인코딩을 사용했다면, 한글이 깨지지 않도록 open() 메서드의 세번째 인자로 encoding = 'utf-8' 입력

<파일 읽기 코드 예시1>

#파일 읽기
with open("user.txt", "r", encoding="utf-8") as file:
    print(file.read()) #파일 전체를 한 번에 읽어들임

with open("user.txt", "r", encoding="utf-8") as file:
    print(file.readline()) #파일을 한 줄씩 읽어들임
    print(file.readline()) 
    #별다른 인덱스 지정 없이도 각각 첫번째, 두번째 문장을 읽어들였다.

with open("user.txt", "r", encoding="utf-8") as file:
    print(file.readlines()) #각 줄을 쭉 읽어서 리스트로 반환

-내장함수 enumerate(리스트) 활용:
리스트의 요소들을 튜플 형태로 (인덱스, 요소값)으로 반환

<파일 읽기 코드 예시2>

with open("user.txt", "r", encoding="utf-8") as file:
    line = file.readline()
    while line:
        print(line.strip()) #공백제거
        line = file.readline()

with open("user.txt", "r", encoding="utf-8") as file:
    lines = file.readlines()
    for idx, value in enumerate(lines):
    #각 튜플에서 첫번째 값을 idx, 두번째 값을 value로 받음
        print(f"{idx}인덱스 값은 {value.strip()}입니다.")

바이너리 파일

바이너리 파일이란?
영상, 이미지, 음성 등이 대부분인 파일로, 0과 1로 이루어진 파일이다.

<파일 모드>
rb: 바이너리 읽기 모드
wb: 바이너리 쓰기 모드 (파일을 새로 생성)
ab: 바이너리 추가 쓰기 모드 (파일 끝에 추가)

바이너리 읽기

<바이너리 읽기 코드 예시>

with open('owl.png', 'rb') as file:
	data = file.read()
    print(f'{len(data} 바이트')
    
with open('owl.png', 'rb') as file:
    header = file.read(10) 
    #parameter size, 몇 바이트를 읽을 건지.
    #디폴트 값은 -1으로, 파일 전체를 읽어들인다.
    print(f'{header}')
#PNG 파일은 항상 b'\x89PNG\r\n\x1a\n'로 시작
#JPEG 파일은 항상 b'\xff\xd8\xff'로 시작

def indentify_file(file_path): #파일의 포맷이 PNG인지 JPEG인지 판정하는 함수
	with open(file_path, 'rb') as file:
    	header = file.read(4)
        print(header)
        if header[:2] == b'\xff\xd8': #JPEG
        	return 'JPEG'
        elif header == b'\x89PNG': #PNG
        	return 'PNG'
        else:
        	return 'unknown format'
            
print(indentify_file('owl.png'))

바이너리 쓰기

<바이너리 쓰기 코드 예시>

#이미지 파일 복사하기
with open('owl.png', 'rb') as source_file:
	data = source_file.read()

with open('owl_copy.png', 'wb') as dest_file:
	dest_file.write(data)
    
print('이미지를 성공적으로 복사했습니다!')

0개의 댓글