파일 열기: fopen()
함수 활용
첫째 인자: 파일 저장 위치와 파일명 지정
윈도우에서 파일경로를 지정할 때 아래와 같이 원(won) 기호를 두 번 사용해야 함.
"C:₩₩test1.txt"
둘째 인자: 파일을 열 때의 옵션 지정
\n
)처리하는 방식이 운영체제마다 다른데 이 문제를 피하려면 바이너리 방식 사용 추천// Visual Studio에서 오류 발생할 경우
// #define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
// 파일에 쓰기: fputs
// 파일에 특정 내용 저장
FILE * file = fopen("test1.txt", "wb"); // 현재 디렉토리에 파일 생성 및 저장
// 파일 열기 가능여부 확인
if (file == NULL)
{
printf("파일 열기 실패\n");
return 1;
}
fputs("fputs를 이용해서 글을 적어볼께요.\n", file);
fputs("잘 적히는지 확인해주세요.\n", file);
// 파일 닫기를 기본적으로 진행.
// 그렇지 않으면 데이터 손실 발생 가능
fclose(file);
return 0;
}
open()
함수의 옵션으로 'b'옵션을 굳이 사용하지 않음.# 파일에 쓰기: write() 메서드
# 파일에 특정 내용 저장
file = open("test1_py.txt", "w") # 현재 디렉토리에 파일 생성 및 저장
file.write("write() 메서드를 이용해서 글을 적어볼께요.\n")
file.write("잘 적히는지 확인해주세요.\n")
# 파일 닫기를 기본적으로 진행.
# 그렇지 않으면 데이터 손실 발생 가능
file.close()
encode()
메서드를 활용하여 bytes 자료형으로 변환시켜야 함.file = open("test1b_py.txt", "wb")
file.write("write() 메서드를 이용해서 글을 적어볼께요.\n".encode())
file.write("잘 적히는지 확인해주세요.\n".encode())
file.close()
with open("test1c_py.txt", "w") as file:
file.write("write() 메서드를 이용해서 글을 적어볼께요.\n")
file.write("잘 적히는지 확인해주세요.\n")
# 파일 닫기는 자동으로 진행됨.
파일이 존재하지 않거나 파일 열기/닫기에 실패하는 경우에 대비하여 예외처리 활용
아래 방식은 오류 종류에 맞추어 예외처리하는 기능 설명
try:
with open("test1d_py.txt", "r") as file:
file.write("write() 메서드를 이용해서 글을 적어볼께요.\n")
file.write("잘 적히는지 확인해주세요.\n")
except IOError as err:
print('파일 오류: ' + str(err))
try:
with open("test1d_py.txt", "r") as file:
file.write("write() 메서드를 이용해서 글을 적어볼께요.\n")
file.write("잘 적히는지 확인해주세요.\n")
except:
print('파일 열기 실패')
// Visual Studio에서 오류 발생할 경우
// #define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define MAX 10000 // 상수 선언
int main()
{
// 파일 읽기 fgets
// 저장된 파일 내용 읽어오기
char line[MAX];
// 읽기 전용으로 열기
// 바이너리 파일로 저장한 경우 바이너리 파일로 읽어와야 함.
FILE * file = fopen("test1.txt", "rb");
// 파일 열기 가능여부 확인
if (file == NULL)
{
printf("파일 열기 실패\n");
return 1;
}
// 한 줄씩 읽어오기
while(fgets(line, MAX, file) != NULL)
{
printf("%s", line);
}
// 파일 닫기를 기본적으로 진행.
// 그렇지 않으면 데이터 손실 발생 가능
fclose(file);
return 0;
}
readline()
함수 활용¶readline()
메서드: 한 줄씩 읽기with open("test1_py.txt", "r") as file:
while 1:
line = file.readline()
if not line: break
print(line)
print()
함수는 줄바꿈을 자동으로 추가함. strip()
메서드 활용하면 문자열의 양 끝에 있는 줄바꿈 기호('\n'
), 스페이스(' '
, 뛰어쓰기) 등의
소위 화이트 스페이스(white space) 등을 제거함.with open("test1_py.txt", "r") as file:
while 1:
line = file.readline().strip()
if not line:
break
print(line)
readlines()
함수 활용¶readlines()
메서드: 모든 줄을 한꺼번에 리스트로 읽어오기. 각각의 줄을 리스트의 항목으로 사용.with open("test1_py.txt", "r") as file:
for line in file.readlines():
if not line:
break
print(line.strip())
try:
with open("test1d_py.txt", "r") as file:
for line in file.readlines():
if not line:
break
print(line.strip())
except:
print("파일 열기 실패")
fprintf()
함수: 서식 문자열을 파일에 저장할 때 사용// Visual Studio에서 오류 발생할 경우
// #define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
// 파일 쓰기 fprintf
// 서식을 지원하는 문자열 저장 함수
// 예제: 로또 번호 저장
FILE * file = fopen("test2.txt", "wb");
if (file == NULL)
{
printf("파일 열기 실패!\n");
return 1;
}
// 로또 추첨번호 저장
fprintf(file, "%s %d %d %d %d %d %d\n", "추첨번호", 1, 2, 3, 4, 5, 6);
fprintf(file, "%s %d\n", "보너스번호", 7);
fclose(file);
return 0;
}
with open("test2_py.txt", "w") as file:
file.write("%s %d %d %d %d %d %d\n" % ("추첨번호", 1, 2, 3, 4, 5, 6))
file.write("%s %d\n" % ("보너스번호", 7))
fscanf()
함수: 파일에 저장된 문자열을 서식에 맞추어 읽어올 때 사용// Visual Studio에서 오류 발생할 경우
// #define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define MAX 10000 // 상수 선언
int main()
{
// 파일 읽기 fscanf
// 서식을 지원하는 문자열 저장 함수
// 예제: 저장된 로또 번호 읽어오기
int num[6] = { 0, 0, 0, 0, 0, 0 }; // 추첨번호 저장용
int bonus = 0; // 보너스 번호 저장용
char str1[MAX];
char str2[MAX];
FILE * file = fopen("test2.txt", "rb");
if (file == NULL)
{
printf("파일 열기 실패!\n");
return 1;
}
// 저장된 로또 추첨번호 읽어오기
fscanf(file, "%s %d %d %d %d %d %d\n", str1,
&num[0], &num[1], &num[2], &num[3], &num[4], &num[5]);
printf("%s %d %d %d %d %d %d\n", str1,
num[0], num[1], num[2], num[3], num[4], num[5]);
fscanf(file, "%s %d\n", str2, &bonus);
printf("%s %d\n", str2, bonus);
fclose(file);
return 0;
}
with open("test2_py.txt", "r") as file:
print("%s %s %s %s %s %s %s" % tuple(file.readline().split()))
print("%s %s" % tuple(file.readline().split()))
비밀읽기 작성하기
fopen()
함수의 a+
옵션
getchar()
와 getch()
의 차이점
getchar()
함수: 엔터가 입력될 때까지 기다린 후 처리getch()
함수: 키 입력 시 바로바로 처리하지만 getch()
함수는 윈도우에서만 지원됨.
Repl.it 사이트 등 처럼 리눅스/맥 환경에서 사용하는 gcc 컴파일러에서는 지원하지 않음.
하지만 아래와 같이 동일한 기능을 하는 함수를 구현할 수 있음.
#include <termios.h>
#include <stdio.h>
static struct termios old, current;
// 새로운 터미널의 i/o 세팅 초기화
void initTermios(int echo)
{
tcgetattr(0, &old); // 이전 터미널의 i/o 세팅 저장
current = old; // 이전 i/o 세팅을 그대로 활용
current.c_lflag &= ~ICANON; // 버퍼를 사용하는 i/o 끄기
if (echo) {
current.c_lflag |= ECHO; // 메아리용 버퍼를 사용하는 모드. 입력한 문자열을 화면에 보여주는 기능.
} else {
current.c_lflag &= ~ECHO; // 메아리용 버퍼를 사용하지 않는 모드. 입력한 문자열을 화면에 보여주지 않음.
}
tcsetattr(0, TCSANOW, ¤t); // 지정한 새로운 i/o 세팅 사용
}
/* 이전 i/o 세팅 복구 */
void resetTermios(void)
{
tcsetattr(0, TCSANOW, &old);
}
/* 한 개의 문자열 읽기 - echo 인자는 버퍼 사용여부 지정 */
char getch_(int echo)
{
char ch;
initTermios(echo);
ch = getchar();
resetTermios();
return ch;
}
/* 메아리 없이 한 개의 문자 읽기. 즉, 입력내용 화면에 보여주지 않음. */
char getch(void)
{
return getch_(0);
}
/* 메아리 사용하며 한 개의 문자 읽기. 즉, 입력내용 화면에 보여줌. */
char getche(void)
{
return getch_(1);
}
동영상과 동일하게 코드 구현 가능
단, 위 코드를 동일 프로젝트 내의 다른 c 파일에 저장했다고 가정함.
extern
지정자를 이용하여 함수를 선언해야 함.#include <string.h>
는 strcmp()
를 사용하기 위해 필요함.
||
활용하였음.// Visual Studio에서 오류 발생할 경우
// #define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
// 다른 c 파일에 저장된 getch() 함수 불러오기
// 동일한 프로젝트의 폴더에 포함된 파일이어야 함.
extern char getch(void);
// 비밀번호를 입력 받아 맞는 경우는 내용 읽어와서 보여주고, 계속 작성하도록 함수
// 비밀번호가 틀린 경우 경고 메시지 출력 후 종료함.
#define MAX 10000 // 상수 선언
int main()
{
// fgets, fputs 활용
char line[MAX]; // 파일에서 불러온 내용 저장
char contents[MAX]; // 일기장에 입력할 내용
char password[20]; // 비밀번호 입력할
char c; // 비밀번호가 입력될 때 한 캐릭터씩 처리하는 용도
printf("'비밀일기'에 오신 것을 환영합니다!\n");
printf("비밀번호를 입력하세요:");
// 비밀번호 입력 처리하기
int i = 0;
while (1)
{
c = getch();
// if (c == 13) // 동영상에서처럼 getch()가 지원되는 윈도우에서 실행하는 경우.
// 13은 '\n'의 아스키 코드
if (c == '\n') // Enter를 가리키는 번호, 즉, 비밀번호 입력 종료 의미
{
password[i] = '\0'; // 비밀먼호 문자열 끝에 추가되는 널 문자 지정
break; // 비밀번호 입력 종료
}
else // 비밀번호 입력 중
{
printf("*"); // 입력되는 비밀번호 마스킹 처리 용도
password[i] = c;
}
i++;
}
// 입력된 비밀번호 확인하기
printf("\n\n === 비밀번호 확인 중 ... ===\n\n");
if (strcmp(password, "skehzheld") == 0) // 비밀번호 = (영어)나도코딩
{
printf("=== 비밀번호 확인 완료 ===\n\n");
char * fileName = "secretdiary.txt";
FILE * file = fopen(fileName, "a+b");
if (file == NULL)
{
printf("파일 열기 실패!\n");
return 1;
}
// 파일 내용 읽어오기
while (fgets(line, MAX, file) != NULL)
{
printf("%s", line);
}
// 내용 추가하기
printf("\n\n 내용을 계속 작성하세요. 종료하려면 EXIT 또는 exit를 입력하세요\n\n");
while (1)
{
scanf("%[^\n]", contents); // 줄바꿈이 사용되기 직전까지 저장. 즉, 한 문단씩 저장.
getchar(); // Enter 키 입력을 flush 처리하기
if (strcmp(contents, "EXIT") == 0 || strcmp(contents, "exit") == 0)
{
printf("비밀일기 입력을 종료합니다.\n\n");
break;
}
fputs(contents, file);
fputs("\n", file); // 줄바꿈을 인위적으로 진행
}
fclose(file);
}
else
{
printf(" === 비밀번호가 틀렸어요. ===\n\n");
printf(" 꺅!! 당신 누가야?!! 감히 내 일기장을 !!!\n\n\n");
}
return 0;
}
파이썬에서는 getch()
에 해당하는 함수 없지만 아래와 같이 구현할 수 있음.
주의사항
getch()
함수는 주피터 노트북에서 작동하지 않음. 참조: OS별 처리
try:
# Windows용 코드
import msvcrt
def getch():
"""단일키 누르는 것을 받아옴"""
return msvcrt.getch()
except ImportError:
# Linux & Mac 용 코드
import sys
import tty
import termios
def getche():
"""단일키 누르는 것을 받아옴
입력된 값도 출력함"""
fd = sys.stdin.fileno()
original_attributes = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, original_attributes)
print(ch)
return ch
def getch():
"""단일키 누르는 것을 받아옴"""
fd = sys.stdin.fileno()
original_attributes = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, original_attributes)
return ch
'\r'
문자열과 비교함. C 언어의 경우와 다름.from getch_termios import getch
print("'비밀일기'에 오신 것을 환영합니다!")
print("비밀번호를 입력하세요:")
password = ''
while True:
c = getch()
if (c == '\r'):
break
else:
print("*", end='', flush=True)
password += c
print("\n=== 비밀번호 확인 중 ... ===\n")
if (password == "skehzheld"):
print("\n=== 비밀번호 확인 완료 ===\n")
fileName = "secretdiary.txt"
with open(fileName, "a+") as file:
for line in file.readlines():
print(line)
print("내용을 계속 작성하세요. 종료하려면 EXIT 또는 exit를 입력하세요\n")
while True:
contents = input()
if (contents == "EXIT" or contents == "exit"):
print("비밀일기 입력을 종료합니다.\n")
break
file.write(contents+'\n')
else:
print("=== 비밀번호가 틀렸어요. ===\n")
print("꺅!! 당신 누가야?!! 감히 내 일기장을 !!!")
try:
password = "skehzheld" # 나도코딩
password[0] = "S"
except:
print("문자열은 수정불가!")
fgets()
함수 또는 readline()
함수 등으로 파일 내용을 읽으면 어디까지 읽었는지를 기억하는 장치가 있음.readline()
함수를 세 번 적용하면 빈 줄이 반환됨.with open("test3_py.txt", "w") as f:
f.write("write() 메서드를 이용해서 글을 적어볼께요.\n")
f.write("잘 적히는지 확인해주세요.\n")
with open("test3_py.txt", "r") as f:
print(f.readline().strip(), 1)
print(f.readline().strip(), 2)
print(f.readline().strip(), 3)
tell()
메서드로 확인 가능with open("test3_py.txt", "w") as f:
f.write("write() 메서드를 이용해서 글을 적어볼께요.\n")
f.write("잘 적히는지 확인해주세요.\n")
with open("test3_py.txt", "r") as f:
print(f.readline().strip(), 1)
print(f.readline().strip(), 2)
print("현재 오프셋 위치:", f.tell())
print(f.readline().strip(), 3)
seek()
메서드를 통해 오프셋 값을 바이트 단위로 지정할 수 있음.with open("test3_py.txt", "w") as f:
f.write("write() 메서드를 이용해서 글을 적어볼께요.\n")
f.write("잘 적히는지 확인해주세요.\n")
with open("test3_py.txt", "r") as f:
print(f.readline().strip(), 1)
print(f.readline().strip(), 2)
print("다시 처음부터...")
f.seek(0)
print("현재 오프셋 위치:", f.tell())
print(f.readline().strip(), 1)
print(f.readline().strip(), 2)
fseek()
, ftell()
함수를 동일한 방식으로 활용하면 됨.#include <stdio.h>
#define MAX 10000
int main()
{
char line[MAX];
FILE * file = fopen("test1.txt", "rb");
fgets(line, MAX, file);
printf("%s", line);
fgets(line, MAX, file);
printf("%s", line);
printf("%ld\n", ftell(file));
// 파일의 현재위치부터 4바이트 뒤로 이동
fseek(file, 4, 1);
printf("%ld\n", ftell(file));
// 파일의 현재위치부터 4바이트 앞으로 이동
fseek(file, -4, 1);
printf("%ld\n", ftell(file));
// 파일의 처음위치부터 0바이트 떨어진 곳으로 이동
// 즉, 파일의 처음으로 이동
fseek(file, 0, 0);
printf("%ld\n", ftell(file));
fgets(line, MAX, file);
printf("%s", line);
fgets(line, MAX, file);
printf("%s", line);
fclose(file);
return 0;
}