C언어 파일 입출력 (1)


C언어  파일 입출력


이번에는 파일 입출력에 대해서 배워보겠다.

파일 입출력이란? 메모장이나 바이너리 파일에 글을 넣거나 글을 불러오거나 이런 것을 뜻한다.

나는 이것을 배울 때 너무 놀라웠다. 너무 신기했고 너무 재미있다.

일단 파일 입출력에 대해서 배우기 전에 스트림에 대해서 배워보자.


스트림이란? 

프로그램과 어떤 것과의 사이에 입출력을 위해서 연결된 통로.

C언어에서 사용하는 표준 스트림은 크게 3가지가 있다.


stdin : 프로그램으로 들어가는 데이터 입력 스트림 ( 키보드 )

stdout : 프로그램이 출력 데이터를 기록하는 스트림 ( 모니터 )

stderr : 오류나 진단을 하기위한 스트림 ( 모니터 )

stderr은 여기서 사용하지 않겠음.

일단 이렇게만 알아두고 나중에 스트림을 사용해서 출력을 해보겠다.

소스코드를 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
int main()
{
    FILE *fp;
    errno_t err = fopen_s(&fp, "C:\\Users\\aossu\\Desktop\\test.txt""w");
    
    if (err != 0) {
        puts("파일 열기 오류");
        return 0;
    }
    fputs("Hello World!!\n", fp);
    
    if (fclose(fp) == EOF)
        puts("파일 닫기 오류");
    return 0;
}
cs


먼저 이 코드를 실행해보면 바탕화면에 test.txt 라는 파일이 생성이 되어있을거다.

 메모장 안을 열어보면 이렇게 나와있다.


소스 분석에 들어가자.


먼저 4행에서 FILE이라는 변수(스트림) fp라는 변수를 만들어준다.

그리고 5행에서 파일을 열 때 사용하는 fopen_s라는 명령어로 파일을 열어준다.

fopen_s(&파일 변수, 경로, 모드) 이렇게 사용하면 된다.

모드에는 이러한 게 있다.


 r

읽기 모드 (반드시 파일이 존재해야 됨) 

 w

쓰기 모드 (파일이 없다면 새로 만듬, 파일이 있다면 내용을 전부 지움) 

 a

 이어쓰기 모드 (파일 맨 끝에 덫붙여서 씀, 파일이 없다면 새로 만듬)

 r+

 읽고 쓰는 모드(파일이 없다면 열지 않음)

 w+

읽고 쓰는 모드 (파일이 없으면 새로 만들고, 있다면 파일 내용을 전부 지움) 

 a+

 읽고 쓰는 모드 (이어쓰기 모드, 파일이 없으면 새로 만듬)

 rb, wb, ab, ab+, wb+ w+b

 위의 모드와 동일하지만 텍스트파일이 아니고 바이너리 파일을 만듬


우리는 w이기 때문에 오로지 쓰기만 가능하다. 읽기는 불가능하다.

그리고 경로에는 저렇게 경로를 안 써주면 프로젝트 폴더 안에 파일이 생성이 된다.

vs2017 기준으로 C:\Users\(컴퓨터 이름)\source\repos\프로젝트 폴더\프로젝트 폴더\ 안에 있다.

나는 바탕화면에 놓는 게 편하니 바탕화면에서 하겠다.

그리고 코드를 보면 C:\\ 이렇게 2개를 써줬다. 그 이유는 \ 하나를 쓰면 escape character라고 해서 이상한 문자가 되어버리므로

\\를 쓰면 \ 하나로 인식을 한다.


그리고 fopen_s를 통해 파일이 열리면 0을 반환하도록 되어있다.

errno_t 변수는 int 타입과 같은데 vs에서 함수의 에러 정보를 표현하기 위한 반환값으로 사용이 된다.

7행에서 0이 반환되지 않았으면 문자를 출력하고 프로그램을 종료한다.


파일이 정상적으로 열렸으면 파일에 Hello world 문자열을 출력한다

fclose는 말 그대로 파일을 종료한다, 끝낸다, 닫는다 이런 말이다.

fclose는 파일이 정상적으로 닫히지 않으면 EOF( -1 ) 을 반환하게 되어있다.


우리가 puts는 화면에 문자를 출력해주지만 fputs는 파일에 문자를 출력해준다.

fputs 사용법은 fputs(문자열, 스트림)이다.

만약 fputs("Hello World!!\n", stdout)이라고 하면



이렇게 화면에 나타나게 되어있다.

stdout은 위에서 설명했듯이 화면에 뿌려주는 파이프라고 생각을 하면 된다.

그래서 fputs("Hello World", fp)를 했을 때 텍스트 파일에 문자열을 출력해준 것이다.


1
2
3
4
5
6
7
#include <stdio.h>
int main()
{
    fclose(stdout);
    printf("aaa");
    return 0;
}
cs

이렇게 stdout 스트림을 닫아버리면


문자열 출력이 안되는것을 볼 수가 있다.



파일에 있는 내용을 입력받아서 콘솔창에 나타내게 해보자.

문자열을 입력 받을때는 gets() 를 사용했으니 fgets() 사용하면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 파일에는 "aossuper8.tistory.com" 이라는 문자열이 들어가있다.
#include <stdio.h>
int main()
{
    FILE *fp;
    char buf[30];
    fopen_s(&fp, "C:\\Users\\aossu\\Desktop\\test.txt""r");
    
    fgets(buf, sizeof(buf), fp);
 
    printf("입력받은 내용 : %s\n", buf);
 
    fclose(fp);
    return 0;
}
cs

< 출력 >


이번에 코드를 보면 if 문이 없다. if 문은 파일을 열 때와 닫을 때 오류는 잘 일어나지 않는다. 그래서 if 문을 없애줬다.

if 문을 사용하지 않으니까 errno_t 변수도 없애줬다.

이번에는 w가 아니라 r형으로 열었다. 읽기 모드로 열어야 읽을 수 있으니까.

fgets 사용법은 fgets(저장될 변수, 사이즈, 파일 스트림) 이렇게 사용하면 된다.

이렇게 하면 파일에 있는 내용이 buf에 사이즈만큼 들어가게 된다.

참 쉽다.


이번에는 한 글자씩 입력받아보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 파일에는 "aossuper8.tistory.com" 이라는 문자열이 들어가있다.
#include <stdio.h>
int main()
{
    FILE *fp;
    char c;
    fopen_s(&fp, "C:\\Users\\aossu\\Desktop\\test.txt""r");
    
    while ((c = fgetc(fp)) != EOF)
        printf("%c", c);
 
    fclose(fp);
    return 0;
}
cs

< 출력 >


fgetc를 통해서 c 변수에 값을 넣고 있다. 그 값이 EOF가 아닐 때까지 값을 입력받고 있다.

파일의 맨 마지막에는 EOF(-1) 값이 들어가 있다.

이 방법을 통해서 파일의 크기를 알아낼 수도 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 파일에는 "aossuper8.tistory.com" 이라는 문자열이 들어가있다.
#include <stdio.h>
int main()
{
    FILE *fp;
    int size = 0;
    fopen_s(&fp, "C:\\Users\\aossu\\Desktop\\test.txt""r");
    
    while (fgetc(fp) != EOF)
        size++;
    printf("파일의 크기 : %d\n"size);
 
    fclose(fp);
    return 0;
}
cs

< 출력 >


EOF가 나오기 전까지만 반복문이 돌으니 21바이트가 나왔다.




파일 위치 지정자
이번에는 위치 지정자에 대해서 알아보자.

여태까지 파일에서 입력을 받을 때 언제나 파일의 시작 부분에서 끝 부분(EOF)까지 쭉 입력 받았다.
이것이 가능하게 된 이유는 파일 위치 지정자 때문이다.
test.txt 파일에 aossuper8이 들어가 있고 우리가 fgetc로 입력 받는다고 가정해보자.

a

o

s

s

u

p

e

r

 8

현재 위치


fgetc로 한 문자를 입력받았다고 하자.


a

o

s

s

u

p

e

r

 8

      ↑

  현재 위치


입력 받았을때 현재 위치는 o에 위치한다. 이렇게 입력 받을때마다 앞으로 한칸씩 이동하게 된다.


그럼 파일 위치 지정자 함수에 대해서 알아보자.

함수에는 fseek라는 함수가 있다.

fseek(파일 스트림, 이동할 수, 어디서부터?) 라고 볼 수 있다.

어디서 부터에는


 SEEK_SET

처음부터

SEEK_CUR

현재부터 

SEEK_END

마지막 부터


이렇게 3가지가 있다.

fseek를 통해서 어느 곳부터 특정 문자를 불러올 수 있다.


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
// 파일에는 "aossuper8.tistory.com" 이라는 문자열이 들어가있다.
#include <stdio.h>
int main()
{
    FILE *fp;
    int c = 0;
    fopen_s(&fp, "C:\\Users\\aossu\\Desktop\\test.txt""r");
    
    c = fgetc(fp);
    fputc(c, stdout);
 
    fseek(fp, 3, SEEK_SET);
    c = fgetc(fp);
    fputc(c, stdout);
 
    fseek(fp, -1, SEEK_END);
    c = fgetc(fp);
    fputc(c, stdout);
 
    fseek(fp, -4, SEEK_CUR);
    c = fgetc(fp);
    fputc(c, stdout);
 
    fclose(fp);
    return 0;
}
cs

출력 값은 알아서 예상 해 보기를 바란다.

답을 댓글로 달아주세요.


댓글

Designed by JB FACTORY