file read and write 코드
*본 게시물은 21-2학기 연세대학교 일반대학원 온라인데이터수집과분석(이상엽 교수님) 수업 내용을 정리한 것입니다.
약 2년 가량 자연어 처리 코드들을 만지면서 제일 많이 접했던 코드는 파일(주로 말뭉치)을 읽어오거나 쓰는 것(주로 전처리한 내용들)이었습니다. BUT 해도해도 맨날 헷갈림 ㅋㅋㅋ
수업 내용 정리할 겸 계속 기억해놓을 겸 정리하려고 합니다.
1. 파일 열고 읽기(open and 'r'ead)
일단 파일을 읽어오는 함수 open()이 있습니다. 이 open()은 인자로 '파일 이름/경로', 와 '모드'를 받습니다.
가령 test.txt라는 파일이 있습니다. 이 파일은 다음과 같은 내용을 담고 있습니다.
--------------------
1
2
3
4
5
----------------------
이 파일을 읽어오기 위해서는 일단 '열어야' 합니다. 즉 open을 사용합니다.
1
|
f = open('C:/Users/사용자이름/폴더1/test.txt', 'r')
|
cs |
상당히 많이 보셨던 코드일 거예요 ㅋㅋㅋ 저는 절대경로를 사용했습니다. 만일 상대경로를 사용할 경우...
1
2
3
4
5
6
|
# 내가 지금 어디있는지 알고 싶어요: 현재 경로 확인하기
import os
os.getcwd()
# 만일 C드라이브 > Users > 사용자 이름> 폴더1에 내가 있을 경우
f = open('./test.txt', 'r')
|
cs |
1
2
3
|
#하나의 문자열로 내용을 돌려주는 read()
f = open('C:/Users/사용자이름/폴더1/test.txt', 'r') f.read()
# 결과: '1\n2\n3\n4\n5'
f.close() |
cs |
결과를 '1\n2\n3\n4\n5'로 리턴하는 것을 볼 수 있습니다. 정말 txt 파일 안의 내용을 몽땅 읽어서 문자열로(그래서 공백 기호까지 표현된) 돌려줍니다.
다음으로 readline()은 '한번에 한 줄만 읽어온 후 문자열로 보여주는' 함수입니다.
참, 만일 같은 노트북 혹은 콘솔 창에서 위의 코드셀과 아래 코드셀을 f.close() 없이 돌리시면 E0F 에러가 납니다ㅠㅠ 실험해 보신 후에는 꼭 f.close()로 닫아주세요ㅋㅋ
1
2
3
4
5
6
7
8
|
# 파일 읽어오기 중 readline(): 한 번에 한 줄만 스트링으로 읽어옴
f= open('C:/Users/사용자이름/폴더1/test.txt', 'r')
f.readline() #'1\n'
f.readline() #'2\n'
f.readline() #'3\n'
f.readline() #'4\n'
f.readline() #'5\n'
f.close() |
cs |
readline()의 경우 한 땀 한 땀 코드를 쳐야 한 줄 씩 내용이 표출되는 것을 볼 수 있습니다. 즉 test.txt에 있었던
--------------------
1
2
3
4
5
---------------------- 의 경우 f.readline()을 5번을 쳐야 전체 내용을 확인할 수 있습니다. -_-;
마지막으로는 readlines()입니다. readlines()는 전체 내용을 라인 별로 읽은 후, 라인 별 내용=원소가 되어 리스트로 저장됩니다. 리스트로 저장되기 때문에 다양한 연산도 가능합니다.
1
2
3
4
|
# readlines()는 라인 별로 내용을 읽은 후, 라인 별 내용= 원소가 되는 리스트를 돌려줍니다.
f= open('C:/Users/사용자이름/폴더1/test.txt', 'r')
f.readlines() #['1\n', '2\n', '3\n', '4\n', '5']
f.close()
|
cs |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
###### 재밌는 연산 ########
# test.txt에 저장된 내용에 5를 더해서 출력해봅시다.
f= open('C:/Users/사용자이름/폴더1/test.txt', 'r')
f.readlines() #['1\n', '2\n', '3\n', '4\n', '5']
numbers = f.readlines()
for k in numbers:
k = k.strip() # 공백을 없애고 ('1', '2', '3', '4', '5')
rest = int(k) # int로 만들어줍니다. (1, 2, 3, 4, 5)
print(rest) # 6 7 8 9 10
f.close()
# 좀 더 fancy한 버전
f= open('C:/Users/사용자이름/폴더1/test.txt', 'r')
numbers1 = f.read() #numbers1 = '1\n2\n3\n4\n5'
f.close()
numbers1.split() # 공백문자 \n을 기준으로 ['1', '2', '3', '4', '5']로
for q in numbers1.split():
print(int(q)+5) # 6 7 8 9 10
|
cs |
2. 파일 쓰기('w'rite)
파일을 열고 읽었으니 이제는 써야합니다. 쓸 때도 마찬가지로 open으로 '쓰고자 하는 빈 파일'을 연 후, 쓰기 모드('w')로 쓰기만 하면 됩니다. 일단 빈 파일을 열고 쓰기 모드라고 정하는 데까지는 다음의 코드를 사용합니다.
1
|
f = open('C:/Users/사용자이름/폴더1/empty_test.txt', 'w')
|
cs |
이 상태에서 empty_test.txt에 본격적인 내용을 쓰려면 어떻게 해야 할까요? wirte() 함수를 써야 합니다. write()의 경우 인자를 하나만 받으며, 문자열을 인자로 받습니다. 때문에 만일 파일에 1을 쓰고 싶으면 f.write(1) 이 아닌, f.write('1')로 써야 합니다.
또한 f.write()를 쓴 이후에는 반드시 f.close()로 닫아주어야 합니다. 그래야 비로소 저장이 완료됩니다.
1
2
|
f.write('this is a test')
f.close()
|
cs |
이 상태에서 쓰기모드로 다시 접근하면 empty_test.txt에 저장된 'this is a test' 는 어떻게 될까요? 기존 내용이 다 사라져버립니다. 때문에 empty_test.txt에 내용을 덧붙이고 싶으면 끼워넣기 모드('a'ppend)를 사용합니다.
1
2
3
4
5
6
7
8
|
f = open('C:/Users/사용자이름/폴더1/empty_test.txt', 'a')
f.write('this is a test2')
f.close()
'''
this is a test
this is a test2
'''
|
cs |
여기까지가 open(), read(), write()에 대한 간단한 내용이었습니다.
수업시간에는 추가로 exercise를 했었습니다. age_test.txt에 있는 2000년도 기준 사람들의 나이를 2021년 기준으로 바꾸고, 그 둘을 같이 출력해서 파일로 만드는 exercise였습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
# exercise
# 2000년도 나이를 2021년 나이로 바꾸고, 그 둘을 같이 출력
f = open('C:/Users/사용자이름/폴더1/age_test.txt', 'r')
age2000= f.read()
f.close()
'''
f.read()는 파일 전체의 내용을 읽어 하나의 문자열로 돌려줍니다. age2000 파일 내용이 '문자열'로 묶인 것을 보실 수 있습니다.
27\n16\n2\n10\n17\n4\n24\n9\n27\n18\n5\n28\n2\n2\n14\n30\n7\n30\n12\n24\n4\n28\n14\n2\n19\n12\n22\n19\n
3\n10\n17\n9\n23\n29\n14\n22\n28\n13\n2\n21\n22\n28\n17\n11\n24\n26\n13\n13\n29\n16\n10\n2\n27\n6\n30\n3
0\n26\n29\n11\n11\n4\n7\n11\n27\n13\n19\n2\n27\n23\n26\n1\n26\n8\n17\n17\n12\n8\n9\n15\n1\n4\n17\n11\n
19\n3\n12\n1\n25\n4\n14\n18\n23\n15\n20\n14\n21\n6\n29\n22\n12\n
'''
f = open('C:/Users/사용자이름/폴더1/age_21.txt', 'w')
for age in age2000.split(): # split()을 통해 공백문자인 \n을 기준으로 리스트를 만듭니다.
age2021 = int(age)+21 # 리스트 안 원소들을 int 상태로 만들고 21을 더합니다.
f.write(str(age)+';'+str(age2021)+'\n') #write() 의 인자는 str여야 하므로 str로 묶습니다.
f.close()
# 헤더 추가 버전
f = open('C:/Users/사용자이름/폴더1/age_21.txt', 'w')
f.write('age2000;age2021\n') #헤더 추가
for age in age2000.split(): # split()을 통해 공백문자인 \n을 기준으로 리스트를 만듭니다.
age2021 = int(age)+21 # 리스트 안 원소들을 int 상태로 만들고 21을 더합니다.
f.write(str(age)+';'+str(age2021)+'\n') #write() 의 인자는 str여야 하므로 str로 묶습니다.
f.close()
|
cs |
3. with ... as ....
파일을 조금 더 안정적으로 읽는 방법입니다. 이 방법을 사용할 경우 f.close()를 명시적으로 불러오지 않아도 됩니다.
사실 이 방법이 더 많이 쓰이기는 합니다. 이에 따라 위에 등장한 f = open(....)을 모두 with open(...) as f: 로 바꿔서 사용할 수 있습니다.
1
2
3
|
with open('C:/Users/사용자이름/폴더1/test.txt', 'r', encoding = 'utf-8') as f:
content = f.read()
content # '1\n2\n3\n4\n5'
|
cs |