FILE * fopen(const char * filename, const char * mode);
FILE 구조체 변수에 파일 정보가 담김 (파일 데이터가 담기는 것이 아님)
#include <stdio.h>
int main()
{
FILE * fp = fopen("data.txt", "wt");
if (fp == NULL)
{
puts("File open failed");
return -1;
}
fputc('A', fp); // 출력의 대상을 파일로 지정.
fputs("BC", fp);
fclose(fp);
return 0;
} |
스트림의 소멸을 요청하는 fclose 함수
#include <stdio.h>
int fclose(FILE * stream);
fclose 함수가 가지는 의미 (써야하는 이유)
- OS는 스트림 형성을 위해 시스템의 자원(주로 메모리)을 할당한다. 이 때 fclose함수를 통해 자원을 반환해준다.
- 두번째로 fclose 함수를 통해 버퍼에 있던 데이터가 출력이 되게 된다. 출력버퍼에 데이터가 존재하는 상황에서 비정상 종료가 될 때 소멸될 수 있는 문제도 있을 수 있다. 이 때문에 버퍼의 데이터가 파일로 바로 저장되도록 fclose 함수를 호출해주는 것이 좋다.
파일 입출력 예제 (파일을 생성해서 문자와 문자열 저장후 읽어들이기)
#include <stdio.h>
int main(void)
{
FILE * fp=fopen("simple.txt", "wt");
if(fp==NULL) {
puts("파일오픈 실패!");
return -1;
}
fputc('A', fp);
fputc('B', fp);
fputs("My name is Hong \n", fp);
fputs("Your name is Yoon \n", fp);
fclose(fp);
return 0;
} |
바로 위 예제 13행에서 \n을 넣지않으면 읽기를 했을 때 문자가 생길 수 있다.
문자열이 파일에 저장할 때는 null문자가 저장되지 않고, 때문에 파일에서는 개행을 기준으로 문자열을 구분하기 때문이다.
#include <stdio.h>
int main(void)
{
char str[30];
int ch;
FILE * fp=fopen("simple.txt", "rt");
if(fp==NULL) {
puts("파일오픈 실패!");
return -1;
}
ch=fgetc(fp);
printf("%c \n", ch);
ch=fgetc(fp);
printf("%c \n", ch);
fgets(str, sizeof(str), fp);
printf("%s", str);
fgets(str, sizeof(str), fp);
printf("%s", str);
fclose(fp);
return 0;
} |
읽어 들일 때는 write순서대로 read해야 저장된 값대로 읽어지는 것을 볼 수 있다. (저장된 값의 순서대로 fputc는 fgetc로 fputs는 fgets로 읽는다.)
스트림은 크게 텍스트 모드 스트림과 바이너리 모드 스트림으로 나뉜다.
텍스트 모드는 사람이 인식할 수 있는 문자 데이터를 저장하고,
바이너리 모드는 컴퓨터가 인식할 수 있는 유형의 데이터이다.
물론 메모리상에는 2진의 데이터로 존재하지만,
문자 데이터는 쉽게 말해 windows 메모장으로 열어서 사람이 쉽게 인식이 가능한 것을 말한다.
그 외에 음원,영상,그림 등은 바이너리 데이터에 포함된다.
스트림 모드중 a mode는 파일의 끝에 덧붙여 쓰는 것으로
파일이 없을 때 생성하는 점은 같지만, 매번 새로 데이터를 쓰는 점은 w와는 다르다.
이외에 + 모드는 읽기/쓰기가 모두 가능한 스트림이지만
양방향 스트림이 실제적으로 쓰이는 경우는 거의 없다고 보면 된다. (필요할 때 스트림을 열고 닫는것이 보통)
텍스트 스트림이 별도로 존재하는 이유
c언어 에서는 \n이 개행을 의미한다.
하지만 os별로 개행의 표시방법이 다르기 때문에
os에 따라 자동변환이 이루어질 수 있는 텍스트 모드를 사용한다.
(읽을 때는 다시 \n으로 복구)
Unix/Linux : \n
Mac : \r
Windows : \r\n
feof 함수
#include <stdio.h>
int feof (FILE * stream);
파일의 끝(End Of File)에 도달한 경우 0이 아닌 값 반환 (읽어들일 데이터가 더 이상 없음을 의미)
파일 입력함수는 오류가 발생했을 때에도 EOF를 반환한다. 아래의 문자와 문자열 단위 파일복사 프로그램에서
파일에 끝에 도달한건지, 오류가 발생한건지 체크를 할 수 있다.
#include <stdio.h>
int main(void)
{
FILE * src = fopen("src.txt", "rt"); // 미리 만들어진 src.txt 파일을 text mode로 읽음
FILE * des = fopen("dst.txt", "wt"); // src.txt의 text를 dst.txt파일에 text mode로 씀
int ch;
if (src == NULL || des == NULL)
{
puts("파일 열기 실패!");
return -1; // -1은 오류를 의미
}
while ((ch=fgetc(src)) != EOF)
{
fputc(ch, des);
}
if (feof(src) != 0)
puts("파일 복사완료!"); // 0이 아닌 값을 반환하면 EOF에 도달했음을 의미
else
puts("파일 복사실패..");
fclose(src);
fclose(des);
return 0;
} |
정상적으로 파일이 복사되면 파일 복사완료! 메시지와 함께 src.txt파일의 text가 dst.txt파일에 복사된 것을 볼 수 있다.
바이너리 데이터의 입력/출력을 위한 함수 fread/fwrite
fread함수
fwrite 함수
#include <stdio.h>
size_t fwrite(void * buffer, size_t size, size_t count, FILE *stream)
fread와 마찬가지로 size는 그 크기만큼 쓰라는 의미이며,
/ * fread/fwrite 를 이용한 바이너라 파일 복사 프로그램 예제
물론 텍스트 모드도 복사의 대상이 될 수 있다.
*/
#include <stdio.h>
int main(void)
{
FILE * src = fopen("src.bin", "rb");
FILE * des = fopen("dst.bin", "wb");
char buf[20];
int readCnt;
if (src == NULL || des == NULL) {
puts("파일오픈 실패!");
return -1;
}
while (1)
{
readCnt = fread((void*)buf, 1, sizeof(buf), src);
// src에서 1 * 20(buf)만큼 읽어 buf에 저장
if (readCnt < sizeof(buf))
// 읽어들인 데이터 크기가 buf[20]의 size보다 작을 때
{
if (feof(src) != 0)
// 에러는 아니지만 20바이트를 못 채웠고 EOF를 반환했을 때
{
fwrite((void*)buf, 1, readCnt, des);
// 마지막으로 읽은 데이터를 파일에 저장
puts("파일복사 완료");
break;
}
else
puts("파일복사 실패");
break;
}
fwrite((void*)buf, 1, sizeof(buf), des);
}
fclose(src);
fclose(des);
return 0;
} |
텍스트 데이터와 바이너리 데이터를 동시 입/출력하기 위한 함수 fprintf / fscanf
fprintf와 fscanf의 사용법은 간단하다. 다만 FILE을 대상으로 조합된 형태대로 입출력하는 점이 다르다.
// frpintf 예제
#include <stdio.h>
int main(void)
{
char name[10];
char sex;
int age;
FILE * fp=fopen("friend.txt", "wt"); // 저장 데이터가 문자열이므로 text mode로 open
int i;
for(i=0; i<3; i++)
{
printf("이름 성별 나이 순 입력: ");
scanf("%s %c %d", name, &sex, &age);
getchar(); // 입력시 \n가 들어가기 때문에 버퍼를 소멸시킴
fprintf(fp, "%s %c %d", name, sex, age);
// fp를 대상으로 조합이 된 문자열(차례대로 문자열,문자,정수)을 저장
}
fclose(fp);
return 0;
} |
/* fscanf 예제
ret(return) */
#include <stdio.h>
int main(void)
{
char name[10];
char sex;
int age;
FILE * fp = fopen("friend.txt", "rt");
int ret;
while (1)
{
ret = fscanf(fp, "%s %c %d", name, &sex, &age);
if (ret == EOF)
break;
printf("%s %c %d \n", name, sex, age);
}
fclose(fp);
return 0;
} |
'코스웨어 > 16년 스마트컨트롤러' 카테고리의 다른 글
2016-08-31_조재찬_스터디일지_C언어-파일의 분할과 헤더파일의 디자인 (0) | 2016.08.31 |
---|---|
2016-08-30_조재찬_스터디일지_C언어-선행처리기와 매크로 (2) (0) | 2016.08.30 |
2016-08-29_조재찬_스터디일지_C언어-선행처리기와 매크로 (0) | 2016.08.30 |
2016-08-28_조재찬_스터디일지_C언어-파일위치 지시자 / 메모리 관리와 동적할당 (0) | 2016.08.29 |
2016-08-24_조재찬_스터디일지_C언어-구조체 (0) | 2016.08.25 |
2016-08-22_조재찬_스터디일지_C언어-문자와 문자열 관련 함수 (0) | 2016.08.23 |
ORCAD 설치시 CPU 100% 사용문제 (0) | 2016.08.08 |
2016-07-05_조재찬_스터디일지-LCD 모듈 제어 (0) | 2016.07.05 |