C/C++

파일 입출력

by MoA posted Jul 28, 2013
?

단축키

Prev이전 문서

Next다음 문서

ESC닫기

크게 작게 위로 아래로 게시글 수정 내역 댓글로 가기 인쇄

http://kid1412org.tistory.com/21


파일의 개방(Open)과 종결(Close)

  • 파일의 개방(open)

    • 파일을 개방한다는 의미는 파일과 데이터를 주고 받을 수 있는 스트림을 생성한다는 뜻
    • fopen : #include<stdio.h> FILE* fopen(const char* filename, const char* mode);이 함수 원형이다.

      • filename은  open 시킬 파일의 경로이다.
      • mode는 oper시킬 파일을 어떤 식으로 열지에 대한 것이다.

 

  • 파일 접근 모드

    • r : 파일을 읽기 위해서 개방한다. only read
    • w : 데이트를 쓰기 위해서 개방한다. only write, 지정해준 파일이 없을 경우 알아서 생성한다.
    • a : 지정해준 파일이 존재하면 데이터를 지우지 않고 그 파일의 끝에서부터 데이터를 추가한다.
    • r+ : 읽고 쓰기 위해 개방한다. 파일이 존재 안할경우 생성하고, 존재할 경우 파일을 지우기는 않고 덮어쓴다.
    • w+ : r+ 모드와 달리 파일이 존재하면 파일 자체를 지워버리고 기록한다.
    • a+ : r+ 모드와 달리 파일이 존재파면 파일의 끝에서부터 데이트를 추가한다.

 

  • 데이터 입.출력 모드

    • t : 텍스트모드
    • b : 2진 모드
    • CR : 특수문자 'r'로 표현되며, 커서의 위치를 그 줄 매 앞으로 이동하라는 의미이다.

#include <stdio.h>
int main()
{
 printf("ABCDEFGr");
 printf("1234567 ");
 return 0;
}

  • 위의 소스에서 보면 r를 써서 ABCDEFG를 찍고 나서 커서를 맨 앞으로 옮기고 그다음에 1234567를 찍기 때문에 ABCDEFG가 사라진다.

    • LF : 특수문자 'n'로 표현되며 커서의 위치를 그 다음 줄로 이동하라는 의미이다. 단, 커서의 위치까지 맨 앞으로 이동하라는 뜻은 아니다


      #include <stdio.h>
      int main()
      {
       printf("ABCDEFGn");
       printf("1234567 ");
       return 0;
      }

  • 위와 같은 소스의 결과를 보면 n에 대한 그림처럼 나오지 않고 rn이 합쳐진 결과값이 나온다.

    • 이유는 아래쪽에서 설명하겠다.

 

  • 텍스트 모드와 2진 모드

    • 2진 모드 : 프로그램상에서 파일로 데이터를 쓰거나 읽어 들이는 경우에 아무런 데이터의 변환도 일으키지 않는 데이터 입출력모드
    • 텍스트 모드 : 프로그램상에서 파일로 데이터를 쓰거나 읽어들이는 경우에 데이터 변환이 일어나는 입출력 모드
    • 텍스트 모드일때 C프로그램에서 n는 rn으로 변형되서 인식을 한다.
    • 따라서 문자열과 같은 텍스트 기반의 데이터는 텍스트 모드로
    • 데이터의 변환이 발생하면 안되는 경우(영상 데이터 입출력 같은)에는 2진 모드로 데이터를 입출력해야한다.

 

  • 파일 개방 모드의 완성

    • 여기서 말하고 싶은건 위에서 파일접근모드와 데이터 입.출력모드의 구성을 조합해서 쓸수 있다는 내용이다.

 

  • FILE 구조체의 포인터(파일 포인터)

    • 지정한 파일과의 데이터 입.출력을 위해 스트림을 생성하는 함수이다.
    • 리턴 값은 무엇인가?

      • FILE이라는 구조체 변수의 포인터이다.
      • FILE 구조체 변수는 개방한 파일에 대한 여러가지 정보를 지니는 변수이다.
    • 무슨 목적으로 사용하게 되는가? 

      •  데이터를 입.출력할때 : FILE 구조체 변수를 참조하면 데이터를 입출력할 파일이 무엇인지 알 수 있다.
      • 위치 정보를 참조 할 때 : FILE 구조체 변수는 파일 내의 위치 정보를 지니고 있다. 이를 참조하면 해당 파일의 어느 위치까지 데이터를 입력 혹은 출력했는지 알 수 있다.
      • 파일의 끝을 확인 할 때 : FILE 구조체 변수를 참조하면 파일의 끝까지 데이터를 읽어 들였는지에 대한 정보를 알 수 있다.

 

  • 파일의 종결(close)

    • fclose : #include<stdio.h> int fclose(FILE* stream)이 함수원형이며 해당 스트림을 소멸 하는게 역할이다.

 #include <stdio.h>
int main()
{
 int state;
 FILE* file = fopen("Test.txt","wt");
 if(file==NULL)
 {
  printf("file open errorn");
  return 1;
 }
 state = fclose(file);
 if (state!=0)
 {
  printf("file close error!n");
  return 1;
 }
 return 0;
}

  •  위에서 오픈모드를 wt로 하였기 때문에 Test.txt라는 이름의 파일이 존재하지 않으면 현재 디렉토리에 파일이 생성될 것이다.

 

II. 파일 입.출력 함수

 

기능 / 스트림키보드/모니터선택(키보드/모니터,파일)
 문자 출력int putchar(int c)int fputc(int c,FILE* stream)
 문자 입력int getchar(void)int fgetc(FILE* stream)
 문자열 출력int puts(cpmst char* s)int fputs(const char*s, FILE* stream)
 문자열 입력char* gets(char* s)char* fgets(char* s,int n,FILE* stream)
 형식 지정 출력int printf(const* format,...)int fprintf(FILE* stream,const char* format,...)
 형식 지정 입력 int scanf(const char* format,...)int fscanf(FILE* stream, const char* format,...)
   
  • fputs 함수를 이용한 파일 출력

#include <stdio.h>
int main()
{
 int state;
 FILE* file = fopen("Test.txt","wt");
 if (file==NULL)
 {
  printf("file open error!n");
  return 1;
 }
 puts("Dont's Worry!");
 fputs("Dont's Worry!n",stdout);
 fputs("Dont's Worry!n",file);
 state = fclose(file);
 if (state!=0)
 {
  printf("file open error!n");
  return 1;
 }
 return 0;
}

  • puts로 문자열을 모니터에 찍고, fputs로 스트림이 stdout이니까 모니터에 출력하고 그다음 fputs에서 스트림이 file이므로 Test.txt  파일에 저장한다.

 

  • fgets 함수를 이용한 파일 입력

#include <stdio.h>
int main()
{
 int state;
 char buf[30];
 FILE* file = fopen("Test.txt","rt");
 if (file==NULL)
 {
  printf("file open error!n");
  return 1;
 }
 fputs("데이터 입력:",stdout);
 fgets(buf, sizeof(buf),stdin);
 puts(buf);
 fgets(buf,sizeof(buf),file);
 puts(buf);
 state = fclose(file);
 if (state!=0)
 {
  printf("file open error!n");
  return 1;
 }
 return 0;
}

  • fgets로 먼저 키보드에서 받아드린 값을 puts로 모니터상에 출력을 하고 두번째 fgets는 file로 부터 문자열을 읽어와서 puts로 출력을 한다.(Test.txt 파일안에 글이 있다면 화면에 찍힌다.)

    • 위 소스에서 문제점은 만약 배열의 크기를 넘어 가면 어떻게 할것인가 이다.
    • 따라서 파일의 끝에 도달했을음 확인할 방법을 찾으면 된다.

 

  • fprintf와 fscanf 함수를 이용한 파일 입.출력

#include <stdio.h>
int main()
{
 int state;
 int i,j;
 int a=0,b=0,c=0;
 char c1=0,c2=0;
 FILE* file = fopen("Test.txt","wt");
 if (file==NULL)
 {
  printf("file open error!n");
  return 1;
 }
 for(i = 2;i<10;i++)
  for(j=1;j<10;j++)
   fprintf(file,"%d * %d = %dn",i,j,i*j);
 state = fclose(file);
 if (state !=0)
 {
  printf("file close error!n");
  return 1;
 }
 file = fopen("Test.txt","rt");
 if (file == NULL)
 {
  printf("file open error!n");
  return 1;
 }
 for(i=2;i<10;i++)
  for (j=1;j<10;j++)
  {
   fscanf(file,"%d %c %d %c %d",&a,&c1,&b,&c2,&c);
   printf("%d %c %d %c %dn",a,c1,b,c2,c);
  }
  state = fclose(file);
  if(state!=0)
  {
   printf("file close error!n");
   return 1;
  }
  return 0;
}

  • 파일 입.출력 함수와 FILE 구조체 변수

    • 파일 위치 지시자 : 파일을 어디까지 읽었는지, 어디까지 썼는지 그 위치를 기억하고 있다는 뜻 이러한 정보를 기억하고 있는 변수

 

III. 파일의 끝을 확인합시다.

  • 리턴 값을 참조하는 방법

 

함수파일의 끝에서 리턴 되는 값
 fgetc EOF(-1)
 fgets NULL 포인터(0)
 fscanf

 EOF(-1)



#include<stdio.h>
int main()
{
 int state;
 char* pState;
 char str[20];
 FILE* file = fopen("Test.txt","rt");
 if (file==NULL)
 {
  printf("file open error!n");
  return 1;
 }
 while (1)
 {
  pState = fgets(str,sizeof(str),file);
  if (pState == NULL)
   break;
  fputs(str,stdout);
 }
 state = fclose(file);
 if (state!=0)
 {
  printf("file close error!n");
  return 1;
 }
 return 0;
}

  • while 문에서 파일의 끝이 나올때 까지 반복하면서 데이터를 읽어 들인다.(참고로 이전에 만들어진 구구단 test.txt를 가지고 하는 것이다.)

 

#include <stdio.h>
int main()
{
 int state;
 char ch;
 FILE* file = fopen("Test.txt","wb");
 if (file==NULL)
 {
  printf("file open error!n");
  return 1;
 }
 fputc('1',file);
 fputc((char)255,file);
 fputc('2',file);
 state=fclose(file);
 if (state!=0)
 {
  printf("file close error!n");
  return 1;
 }
 file = fopen("Test.txt","rb");
 if (file==NULL)
 {
  printf("file open error!n");
  return 1;
 }
 while (1)
 {
  ch = fgetc(file);
  if (ch == -1)
   break;
  printf("data : %cn",ch);
 }
 state = fclose(file);
 if (state!=0)
 {
  printf("file close error!n");
  return 1;
 }
 return 0;
}

  • 결과값을 찍어 보자

    • 위에서 1, (char)255, 2 를 저장하였음에도 불구하고 1만 출력되는 것을 볼 수 있다.
    • (char)255는 10진수로 -1이다. 그런데 while문에서 -1이 file 안에 있다면 반복문을 빠져 나오는 것인데 (char)255를 -1으로 인식하여 종료가 되는 것이다.

 

#include <stdio.h>
int main()
{
 int state;
 int ch;
 FILE* file = fopen("Test.txt","wb");
 if (file==NULL)
 {
  printf("file open error!n");
  return 1;
 }
 fputc('1',file);
 fputc((char)255,file);
 fputc('2',file);
 state=fclose(file);
 if (state!=0)
 {
  printf("file close error!n");
  return 1;
 }
 file = fopen("Test.txt","rb");
 if (file==NULL)
 {
  printf("file open error!n");
  return 1;
 }
 while (1)
 {
  ch = fgetc(file);
  if (ch == -1)
   break;
  printf("data : %cn",ch);
 }
 state = fclose(file);
 if (state!=0)
 {
  printf("file close error!n");
  return 1;
 }
 return 0;
}

  •  위 소스는 이전 소스에서 char ch를 int ch로 바뀐 점이다.

    • 여기에 대한 설명은 아직 제대로 이해를 못해서 책을 봐주세요 ;;;

 

  • feof 함수를 사용하는 방법

    • feof : #include<stdio.h> int feof(FILE* stream)이 함수 원형이며 호출시 전달되는 파일 포인터가 가리키는 파일이 끝에 도달한 경우 0이 아닌 값을 리턴한다.

 

#include <stdio.h>
int main()
{
 int state;
 char ch;
 FILE* file = fopen("Test.txt","wb");
 if (file==NULL)
 {
  printf("file open error!n");
  return 1;
 }
 fputc('1',file);
 fputc((char)255,file);
 fputc('2',file);
 state=fclose(file);
 if (state!=0)
 {
  printf("file close error!n");
  return 1;
 }
 file = fopen("Test.txt","rb");
 if (file==NULL)
 {
  printf("file open error!n");
  return 1;
 }
 while (1)
 {
  ch = fgetc(file);
  if (feof(file)!=0)
   break;
  printf("data : %cn",ch);
 }
 state = fclose(file);
 if (state!=0)
 {
  printf("file close error!n");
  return 1;
 }
 return 0;
}


  • 책에서 나온 실행 결과는 잘못된 것이고 p.558에 있는 실행결과처럼 나와야 한다.

    • 이전 소스에서는 while문 안에 if(ch == -1) 일때 반복문을 빠져 나오게 하였지만 좋지 못한 결과가 나오기도 했다.

      • 그러나 feof를 써서 0이 아닌 값 즉 파일의 끝에 도달하면 0이 아닌 값을 리턴 할때 반복문을 빠져 나오게 한다.

 

IV. Random Access 파일 입.출력

  • fseek : #include<stdio.h> int fseek(FILE* stream, long offset, int wherefrom)이 함수원형

    • 파일 위치 지시자를 원하는 위치에 놓을 수 있다.  stream이 가리키는 파일의 파일 위치 지시자를 시작 위치 wherefrom에서부터 offset 만큼 이동한다.
만약에 wherefrom이파일 위치 지시자를 offset 만큼 이동하기 전에
 SEEK_SET(0)이라면 파일의 맨 앞으로 이동한다.
 SEEK_CUR(1)이라면 이동하지 않는다.
 SEEK_END(2)이라면

 파일의 끝으로 이동한다.




#include <stdio.h>
int main()
{
 char buf[10];
 FILE* file = fopen("Test.txt","wt");
 fputs("1234abcd56789",file);
 fclose(file);
 file = fopen("Test.txt","rt");
 fgets(buf,7,file);
 printf("%sn",buf);
 fseek(file, 2, SEEK_CUR);
 printf("%cn",fgetc(file));
 fseek(file,-2,SEEK_CUR);
 printf("%cn",fgetc(file));
 fseek(file,2,SEEK_SET);
 printf("%cn",fgetc(file));
 fseek(file,-2,SEEK_END);
 printf("%cn",fgetc(file));
 fclose(file);
 return 0;
}



Articles

1 2 3 4 5 6 7 8 9 10