티스토리 뷰

Programming/C언어

[C/C++] 파일 입출력 01

Lkt_Programmer 2017. 10. 14. 22:23
반응형

1. 파일의 개방과 종결


 

파일로부터 데이터를 입출력하기 위해서는 제일 먼저 파일을 열어야 합니다. 파일을 열겠다는 의미는 파일과 데이터를 주고 받을 수 있는 스트림을 생성한다는 의미입니다. C언어에서 파일을 열기 위한 함수로 fopen_s 함수를 제공합니다.  

 

1
2
3
4
5
int main()
{
    FILE* f;                        //파일포인터 변수
    fopen_s(&f,"Test.txt","rt");    //fopen_s 함수 호출 
}

 

fopen_s 함수는 총 3개의 인자를 가집니다. 첫 번째 인자는 파일이 성공적으로 개방하면 리턴되는 파일 구조체의 포인터 값을 저장 할 변수가 옵니다. 두 번째로는 열고자 하는 파일의 경로가 오게 되고 프로젝트와 같은 위치에 존재한다면 파일 이름만 오면 됩니다. 세 번째 인자는 개방하는 파일의 특징 및 용도를 결정짓습니다. file의 개방 모드는 파일 접근 모드와 데이터 입출력 모드가 더해져서 하나의 개방 모드를 이루게 됩니다.

 

파일 접근 모드


 모드

 의미

 r

파일을 읽기 위해서 개방, 오로지 읽는 것만 가능

데이터를 쓰기 위해 개방, 오로지 쓰는 것만 가능하다. 만약 지정해준 파일이 존재하지 않으면 새로운 파일을 생성해서 데이터를 쓰게 된다.

w 모드와 달리, 지정해준 파일이 존재하면 데이터를 지우지 않고 파일의 끝에서부터 데이터를 추가한다.

r+

파일을 읽고 쓰기 위해 개방한다.

w+ 

r+와는 달리 지정해준 파일이 존재하면 모든 데이터를 지워버리고 데이터를 기록한다.

a+ 

r+와는 달리 지정해준 파일이 존재하면 파일의 끝에서부터 데이터를 추가한다.

 

데이터 입출력 모드


데이터 입출력 모드란 데이터를 입력 혹은 출력하는 방식을 의미합니다. 다음과 같은 두 가지 입출력 모드를 정의합니다.

 

 t

 텍스트 모드 (text mode)

 b

 2진 모드(binart mode) 

 CR(Carriage Return)

특수 문자 '\r'로 표시가 되면 줄을 바꾸지 않고 커서를 맨 앞으로 이동 시킵니다. 

 LF(Line Feed)

특수 문자 '\n'으로 표시가 되면 커서의 위치를 그 다음 줄로 이동하라는 의미입니다. 현재 커서의 위치에서 줄만 바꾸게 됩니다. 

 

2진 모드란 프로그램상에서 데이터를 쓰거나 읽어 들이는 경우에 아무런 데이터의 변환도 일으키지 않는 모드입니다. 반면에 텍스트 모드는 데이터를 쓰거나 읽어 들이는 경우에 데이터의 변환이 일어나는 모드를 의미합니다.

텍스트 모드의 데이터 입출력의 경우에는 C프로그램상에서 \n이 텍스트 파일상으로는 \r\n으로 변환이 되고 반대로 텍스트 파일상에서 \r\n은 프로그램상에서 \n으로 변환이 됩니다. 반면에 2진 모드에서는 아무런 변환도 일어나지 않습니다.

 

다음은 파일을 개방하고 닫아주는 예제입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main()
{
    FILE* f;                        
    fopen_s(&f,"Test.txt","rt");        //파일을 읽기 위한 모드+텍스트 모드로 개방
    if (f == NULL)                        //Null이면 파일 개방에 실패
    {
        printf("File Open Error");
    }
 
    if (fclose(f) != 0)                    //파일 닫아줌
    {
        printf("File Close Error");
    }
    return 0;
}

 

프로그램이 종료되면 자동으로 파일이 닫히지만 반드시 프로그램상에서 명시적으로 파일을 닫아주는게 좋습니다.

 

2. 파일 입출력 함수


 

■ fputs 함수


먼저 소개하는 함수는 fputs 함수입니다. fputs 함수는 puts 함수와 기능은 같지만 출력하고자 하는 스트림이 결정되어 있지 않습니다. fputs 함수 호출 시 첫 번째 인자로 출력하고자 하는 문자열을 전달하고, 두 번째 인자로 stdout을 전달하는 경우, stdout은 모니터로 데이터를 전송하는 스트림을 의미하기 때문이 문자열이 모니터로 출력됩니다. 이 경우에는 puts 함수와 같은 기능을 지니게 됩니다. 두 번째 인자로 파일 갱바 시 리턴한 포인터를 인자로 전달하게 되면, 해당 파일에 문자열이 저장이 됩니다. 파일 포인터는 스트림을 의미하기 떄문입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main()
{
    FILE* f;                        
    fopen_s(&f,"Test.txt","wt");            //파일 개방
    if (f == NULL)
    {
        printf("File Open Error");
    }
 
    fputs("Hello World!!!!\n", stdout);        //문자열 모니터상에서 출력
    fputs("Hello World !!!!\n", f);            //파일에 문자열 저장
 
    if (fclose(f) != 0)                        //파일 종결
    {
        printf("File Close Error");
    }
    return 0;
}

 

4번째 라인에서 파일을 개방합니다. 파일 접근 모드 방식은 'w' 텍스트 접근 방식은 't'로 합니다. 

그리고 10번째 라인에서 fputs() 함수를 호출합니다. 두 번째 인자가 stdout이므로 모니터로 전송하는 스트림으로 결정하게 됩니다. 반면에 11번째 라인에서 fputs 함수의 경우 두 번째 인자가 파일 포인터가 오고 있습니다. 파일 포인터는 파일로 전송하는 스트림을 의미하므로 첫 번째 인자의 문자열이 파일에 저장이 됩니다.

 

■ fgets 함수


fgets 함수를 활용하여 파일 안에 존재하는 문자열을 읽어들입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int main()
{
    FILE* f;                    
    char buf[30];
 
    fopen_s(&f,"Test.txt","rt");            //파일 개방
    if (f == NULL)
    {
        printf("File Open Error");
    }
 
    fgets(buf, sizeof(buf), stdin);            //키보드로부터 입력 스트림 지정
    puts(buf);
 
    fgets(buf, sizeof(buf), f);                //파일로부터 입력 스트림 지정
    puts(buf);
 
    if (fclose(f) != 0)                        //파일 종결
    {
        printf("File Close Error");
    }
    return 0;
}

 

12번째 fgets 함수를 호출합니다. 세 번째 인자로 입력 스트림을 지정하는데 'stdin'으로 지정하고 있습니다. stdin은 키보드로부터 입력 받는 스트림을 지정한다는 의미입니다. 반면에 15번 라인에서 fgets 함수의 세 번째 인자에서 파일 포인터를 지정함으로써 파일로부터 입력을 받는다는 의미입니다.

 

■ 파일위치 지시자


임의의 파일을 개방하고, 데이터를 읽어들이기 위한 함수를 여러 번 호출하면 이전에 읽어들인 부분의 뒤를 이어서 데이터를 읽어들입니다. 이러한 일이 가능한 것은 파일을 어디까지 읽었는지, 혹은 어디까지 썼는지, 그 위치를 기억하고 있다는 뜻입니다. 이러한 정보를 기억하고 있는 변수를 가리켜 파일 위치 지시자라고 합니다.

 

이러한 파일 위치 지시자는 파일을 개방 하였을 때 반환하는 파일 구조체 변수내에 존재하게 됩니다. 이 변수는 파일 내의 위치 정보를 지니고 있으며, 이 변수의 값은 파일에서부터 데이터를 읽거나 쓰는 경우 변경이 됩니다. 그렇기 때문에 순차적인 파일에 대한 입출력이 가능해집니다.

 

3. 파일의 끝을 확인하자


파일에서부터 데이터를 읽어들일 때 파일의 존재하는 모든 데이터를 읽어들였다는 것을 확인하는 방법이 필요합니다.

 

■ 리턴 값으로 확인하는 방법


파일로부터 데이터를 읽어들이는데 사용되는 함수들은 파일의 끝에 도달하는 경우에 정해진 값을 리턴합니다.

 

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
int main()
{
 
    FILE* f;                    
    char* state;                            //파일끝을 확인하는 변수
    char str[20];                            //파일로부터 읽어들인 데이터가 저장될 변수
 
    fopen_s(&f,"Test.txt","rt");            //파일 개방
    if (f == NULL)
    {
        printf("File Open Error");
    }
 
    while (1)
    {
        state = fgets(str, sizeof(str), f);    //파일 끝에 도달하면 NULL반환
        if (state == NULL)                    //NULL일경우 break;
            break;
        fputs(str, stdout);
    }
 
    if (fclose(f) != 0)                        
    {
        printf("File Close Error");
    }
    return 0;
}

14라인에서 20라인까지 반복문을 수행합니다. 16라인에서 fgets 함수를 통해 파일에서 데이터를 읽어오고 파일의 끝 여부를 판단해줄 값을 반환합니다. 해당 반환값이 NULL(파일의 끝에 도달한 경우)일 경우 반복문을 빠져나옵니다.

 

■ feof 함수를 이용하는 방법


두 번째 방법은 feor 함수를 사용하는 방법입니다. feof 함수를 호출하면서 파일 포인터를 전달하게 되면 파일의 끝에 도달했는지에 대한 정보를 리턴 해줍니다.

 

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
int main()
{
 
    FILE* f;                    
    char str[20];                            //파일로부터 읽어들인 데이터가 저장될 변수
 
    fopen_s(&f,"Test.txt","rt");            //파일 개방
    if (f == NULL)
    {
        printf("File Open Error");
    }
 
    while (1)
    {
        fgets(str, sizeof(str), f);        //파일끝에 도달할경우 0이 아닌 값을 리턴한다.
        fputs(str, stdout);
        if (feof(f) != 0)                    
            break;    
    }
 
    if (fclose(f) != 0)                        
    {
        printf("File Close Error");
    }
    return 0;
}

 

15,16번 라인에서 파일에서부터 데이터를 읽어와 모니터에 출력해주고 있습니다. 17번 라인에서 feof함수를 호출함으로써 파일 끝에 도달했는지에 대한 여부를 판단하고 있습니다. feof 함수는 파일끝에 도달할 경우에 0이 아닌 값을 리턴 해줍니다.

 

 

 

 

 

 

 

 

 

 

반응형