파일과 스트림
구현한 프로그램에서 데이터를 불러올때, 프로그램과 참조할 데이터 사이의 데이터가 이동할 수 있는 다리를 스트림이라한다.
fopen 함수호출을 통한 스트림형성과 FILE 구조체
#include<stdio.h>
FILE * fopen (const char * filename, const char * mode); // 성공시 해당파일의 FILE 구조체 변수의 주소값 , 실패시 NULL포인터 반환
FILE 구조체의 포인터는 파일을 가리키기 위한 용도로 사용된다. 즉, 이 포인터를 이용해서 파일에 데이터를 저장하거나 파일에 저장된 데이터를 읽게된다.
입력스트림과 출력스트림의 형석
FILE * fp1 = fopen ("data.txt","wt"); // 출력스트림, 파일 data.txt와 스트림을 형성하되 , wt 모드로 스트림을 형성
FILE * fp2 = fopen ("data.txt","rt"); // 입력스트림, 파일 data.txt와 스트림을 형성하되 , rt 모드로 스트림을 형성
FILE * fp3 = fopen ("C:\\Project\\data.txt","wt"); // 출력파일이 생성될 위치를 지정할 수 있다.
if(fp1=NULL) // 파일오픈이 정상적으로 됐는지 검사
{
printf("파일오픈실패!\n");
return -1; // 비정상적인종료일때 -1값반환
}
fputc('A',fp1); // 출력스트림 fp1을통해 data.txt에 A 문자 출력
int ch = fgetc(fp2); // 입력스트림 fp2를통해 data.txt로부터 A값을 불러옴
스트림의 소멸을 요청하는 fclose 함수
#include <stdio.h>
int fclose(FILE * stream); // 성공시 0 , 실패시 EOF 반환
fclose함수의 호출을통해 개방되었던 파일을 닫아줘야하는 이유
운영체제가 할당한 자원의 반환
버퍼링 되었던 데이터의 출력 // 운영체제가 정해놓은 버퍼링방식에따라 파일저장하는때가 다르기때문에 , fclose함수로 데이터를 출력해주는게좋다.
스트림을 종료하지않고 버퍼를 비울때는 fflush 함수
#include<stdio.h>
int fflush( FILE * stream); // 함수호출 성공시 0 , 실패시 EOF 반환
파일의 개방모드
스트림을 구분하는 기준1 : 읽기위한스트림, 쓰기위한스트림
모드 r : 읽기가능 , 파일없을시 에러출력
모드 w : 쓰기가능 , 파일없을시 파일생성
모드 a : 파일의끝에 덧붙여쓰기가능 , 파일없을시 파일생성
모드 r+ : 읽기/쓰기가능 , 파일없을시 에러출력
모드 w+ : 읽기/쓰기가능 , 파일없을시 파일생성
모드 a+ : 읽기/덧붙여쓰기가능 , 파일없을시 파일생성
//웬만하면 r , w , a 를 사용하여 입력스트림과 출력스트림을 따로 생성해 사용하는것이 좋다.
스트림을 구분하는 기준2 : 텍스트모드와 바이너리모드
사람이 인식할수 있는 문자를 담고있는 파일을 가리켜 텍스트파일이라고 하며 , 그 이외에 컴퓨터가 인식할 수 있는 데이터를 파일을가리켜 바이너리파일이라고 한다. 이때 , 개행( \n)이 C언어에서만의 개행표시인데, 이것을 텍스트모드로 개방할때는 , 개행을 각 환경에 맞는 개행표시로 변환해준다. 바이너리모드는 개행을 변환하지않는다.
텍스트 모드
rt , wt , at , r+t , w+t , a+t
바이너리모드
rb , wb , ab , r+b , w+b , a+b
파일 입출력함수
int fputc(int c,FILE * stream); // 문자 출력
int fgetc(FILE * stream); // 문자입력
int fputs(const char * s , FILE * stream ); // 문자열 출력
char * fgets(char * s , int n , FILE * steam); // 문자열 입력
ex)
char str[30];
FILE * fp = fopen("simple.txt","wt");
if(fp == NULL) // fopen 함수는 파일오픈실패시 NULL반환
{
puts("파일오픈실패!\n");
return -1;
}
fputs("MY NAME IS HONG\n",fp); //문자열을 simple.txt 파일에 출력할때 , 개행키워드(\n)가 포함되었기때문에 txt파일로 파일을 개방해야한다. 또한, 파일에 문자열을 출력할때는 널문자가 포함되지않기때문에 , 개행키워드가(\n) 문자열을 구분하는 기준이된다.
fgets(str,sizeof(str),fp);
printf("%s",str); // MY NAME IS HONG\n 출력
파일의 끝을 확인하는 함수 : feof
#include <stdio.h>
int feof(FILE *stream); // 파일의 끝에 도달한경우 0이 아닌값 반환
ex)
FILE * src = fopen("src.txt","rt");
FILE * des = fopen("des.txt","wt");
while ( fgets(str,sizeof(str),src)!=NULL)//fgets 함수는 읽을 데이터가 없을때 NULL을 반환한다
//or while(fgetc(n,src) != EOF) // fgetc함수는 읽을데이터가없을때 EOF반환
{
fputs(str,des);
}
if(feof != 0)
printf("파일복사성공!\n");
else
puts("파일복사실패!\n");
fclose(src);
fclose(des);
바이너리 데이터의 입출력 : fread , fwrite
#include<stdio.h>
size_t fread(void * buffer,size_t size , size_count,FILE* stream);// 성공시 전달인자 count, 실패 또는 끝 도달시 count보다 작은값 반환
ex)
int buf[12];
fread((void *)buf,sizeof(int),12,fp);//sizeof(int) 크기의 데이터 12개를 fp로부터 읽어들여서 buf 에 저장하라
#include<stdio.h>
size_t fwrite(const void * buffer,size_t size ,size_t count , FILE * stream);//성공시 전달인자 count ,실패시 count 보다 작은 값 반환
ex)
int buf[7]={1,2,3,4,5,6,7};
fwrite((void*)buf,sizeof(int),sizeof(buf)/sizeof(int),fp); // sizeof(int)크기의 데이터 sizeof(buf)/sizeof(int)개를 fp로 출력하라
텍스트 데이터와 바이너리 데이터 동시에 입출력하기
서식에 따른 데이터 입출력 : fprintf , fscanf
fprintf의 사용법
ex)
char name[10]="홍길동";
char sex = 'M';
int age =24;
fprintf(fp,"%s %c %d",name,sex,age); // fp가 첫번째 전달인자 , fprintf 함수를 통해 "홍길동 M 24" 라는 문자열이 만들어지고 , 이렇게 만들어진 문자열이 첫번째 전달인자가 가리키는 파일에 저장된다. 즉 , 텍스트데이터와 바이너리데이터를 하나의 문자열로 묶어서 저장하는셈이다.
scanf("%s %c %d",name,&sex,&age);
getchar(); // scanf함수는 \n을 읽어들이지않고 입력버퍼에 남겨두기때문에 getchar();함수를 이용해 \n을 소멸시켜줘야한다
fprintf(fp,"%s %c %d",name,sex,age);
fclose(fp);// fp스트림 소멸
fscanf의 사용법
fscanf 함수는 파일의 끝에 도달하거나 오류가 발생하면 EOF 를 반환한다
ex)
int ret;
char name[10];
char sex;
int age;
FILE * fp =fopen("friend.txt","rt");
while(1)
{
ret = fscanf(fp,"%s %c %d",name,&sex,&age);
if(ret ==EOF) // ret 값이 EOF라면 파일의 끝 도달 혹은 오류발생
break;
printf("%s %c %d",name,sex,age);
}
fclose (fp);
텍스트와 바이너리 데이터의 집합체인 구조체변수의 출력
구조체변수를 하나의 바이너리데이터로 인식하고 처리한다 // fread 함수 혹은 fwrite 함수를 이용한다
ex)
Friend myfriend1;
Friend myfriend2;
FILE * fp;
fp=fopen("friend.bin","wb");
...
fwrite((void*)&friend1,sizeof(myfriend1),1,fp); // myfriend1에서 sizeof(myfriend1)만큼의 데이터를 1번 fp 스트림을통해 출력
fclose(fp)
fp=fopen("friend.bin","rb");
fread((void *)&myfriend2,sizeof(myfriend2),1,fp); // myfriend2 에 sizeof(myfriend2 ) 만큼의 데이터를 1번 fp 스트림을 통해 입력
임의 접근을 통한 '파일 위치 지시자'의 이동
FILE 구조체의 멤버중 파일의 위치정보를 저장하고있는 멤버가있는데, 이 멤버의 값은 fgets,fputs,fread,fwrite와 같은 함수가 호출 될 때마다 참조 및 갱신되며, 이 멤버가 가리키는 위치를 시작으로 문자열을 읽어들이게된다. 이 멤버를 가리켜 '파일위치 지시자'라고 부른다. 파일위치 지시자는 처음 파일이 개방되면 무조건 파일의 맨 앞부분을 가르킨다.
파일위치 지시자의 이동 : fseek
#include<stdio.h>
int fseek(FILE * stream, long offset, int wherefrom); // 성공시 0 , 실패시 0 이아닌값을 반환
// stream 으로 전달된 파일위치지시자를 wehrefrom에서부터 offset 바이트만큼 이동시켜라
매개변수 wherefrome이
SEEK_SET 이라면 파일위치지시자는 파일 맨앞에서부터 이동을시작
SEEK_CUR이라면 파일위치지시자는 현재위치에서부터 이동을 시작
SEEK_END이라면 파일위치지시자는 파일 맨뒤에서부터 이동을시작 // 이때 , 파일의 끝 (EOF)에서부터 이동을시작
//offset에는 양의 정수뿐만아니라 음의정수도 전달될 수 있다. (음의정수 전달시 앞으로 , 양의정수전달시 뒤로 이동)
현재 파일위치지시자의 위치 : ftell
#include< stdio.h>
long ftell(FILE * stream); //파일위치지시자의 위치정보 반환
'C언어 > 열혈C' 카테고리의 다른 글
C : Chapter -22 매크로와 선행처리기 (0) | 2018.04.07 |
---|---|
C : Chapter -21 메모리 관리와 메모리의 동적할당 (0) | 2018.04.04 |
C : Chapter -19 공용체와 열거형 (0) | 2018.03.30 |
C : Chapter -18 구조체와 사용자 정의 자료형 (0) | 2018.03.27 |
C : Chapter-17 문자와 문자열 관련 함수 (0) | 2018.03.27 |