파일 입.출력
파일 입.출력은 앞으로도 매우 중요하게 쓰이는 부분이다.
어떤 파일로부터 데이터를 읽어들이고 또 데이터를 어떤 파일에 저장하는 것을 말한다.
데이터 저장과 불러오기 기능을 구현한것
읽기 / 쓰기 전용 , 읽기 / 쓰기 혼합 모드 기능
파일을 열고 닫는 작업이 쌍으로 존재한다.
* FILE *fopen(const char *filename, const char *mode) ; // 성공시 해당파일의 포인터. 실패시 NULL 포인터 리턴
- filename : 문자형 포인터로 사용할 파일 이름을 지정
- mode : 파일에 대한 접근 방식
- 리턴값 : open 한 파일을 가리키는 파일 포인터
mode 에는 기본적으로 r, w, a 가 있고 세부적으로 바이너리 코드(이진모드)와 텍스트 모드로 분리
[파일 오픈 모드]
r 텍스트 모드이며 읽기 모드로 파일을 오픈
w 텍스트 모드이며 쓰기 모드로 파일을 오픈. 단 파일을 없으면 자동으로 생성. 있으면 내용을 전부 삭제하고 새로운 파일을 생성
a 텍스트 모드이며 쓰기 모드로 파일을 오픈. 단 파일이 없으면 자동으로 생성. 있으면 파일의 가장 끝부분에 이어 쓰기를 실행
b 바이너리 모드를 의미
+ 읽기 / 쓰기의 혼합 모드가 가능함을 의미
[데이터 입.출력 모드]
t 텍스트 모드(text mode)
b 2진 모드(binary mode)
데이터의 읽기 / 쓰기를 텍스트 모드로 할건지 2진 모드로 할건지 정해주는 거이다.
문자열과 같은 텍스트 기반의 데이터는 텍스트 모드로 입. 출력 하는 것이 좋고 데이터 변환이 발생하면 안되는 경우 2진 모드로 데이터 입. 출력 하는 것이 좋다.
파일 접근 모드 + 데이터.입출력모드 = 파일 개방 모드 rt ( r + t ) : 텍스트 모드의 읽기 전용
[일반적인 파일 열기 방법과 파일 오픈시 주의 사항]
FILE *fp ; // 파일을 오픈하기전에 반드시 파일포인터 선언
.......
fp = fopen( "test.txt" , "r" ) ; // 파일이름과 모드는 "와" 사이에 입력 test.txt 파일을 읽기 모드로 읽는 것이다.
....... // 반드시 test.txt 파일이 폴더내에 있어야 한다.
if( fp == NULL ) // 파일이 제대로 열렸는지 반드시 체크
{
........
return -1 ;
}
[파일 종결]
* int fclose(FILE *stream) ;
- stream : fopen() 함수를 통해 생성된 파일 포인터
- 현재 열린 파일을 닫을때 사용
- 출력 버퍼에 남아있는 데이터를 파일에 기록한 후 파일을 닫음
FILE *fp ;
.......
fp = fopen( "test.txt", "r" ) ; // 파일 오픈
.......
fclose( fp ) ; // 파일 닫음
동적할당에서 malloc 과 free 가 짝이 듯이 항상 파일을 오픈하면 종료를 해주어야 한다. fopen -> fclose
* 파일을 읽기 와 쓰기 에서 사용되는 함수들은 기존의 함수와 비슷하다. f 만 들어가면 된다.
하나의 문자를 파일에 저장
int fputc(int c, FILE *fp) ;
- c : 파일에 저장할 데이터
- fp : open 한 파일을 가리키는 포인터
- 리턴값 : fputc() 함수가 파일에 기록한 데이터
#include <stdio.h>
void main()
{
FILE *fp ;
fp = fopen( "text.txt", "w" ) ; // w 생성한다. test.txt 기존에 파일이 있으면 데이터 삭제 새로 사용.
for( int i = 0 ; i <128 ; i++ ){
fputc( '\n', fp ) ;
fputc( i, fp ) ;
}
fclose( fp ) ;
}
실행하면 아무것도 안나올 것이다.. 폴더에 가보면 test.txt 란 파일이 생기고 아스키 코드값 0번부터 128번의 문자들이 들어있다.
<fgetc() 함수>
* int fgetc( FILE *fp ) ;
- fp : fopen() 함수를 통해 생성된 파일 포인터
- 리턴값 : 문자
- fp 는 항상 NULL 이 될수 없음
폴더에 text.txt 안에 a b c 를 작성하고 종료.(저장. 공백 주의)
#include <stdio.h>
#include <stdlib.h>
void main()
{
FILE* fp ;
fp = fopen( "test.txt" , "r" ) ;
if( fp == NULL){
printf("Error\n") ;
exit( 1 ) ;
}
while( !feop(fp) ) // 끝이 아니라면 실행
printf( "%c", fgetc(fp) ) ; // 문자를 읽어들여 출력 a b c 출력
fclose( fp ) ;
}
<feop() 함수>
* int feop( FILE *filepointer )
- fileopinter : fopen() 함수를 통해 생성된 파일 포인터
- 현재 가리키는 위치가 파일의 끝인가를 검사한다.
- 리턴값 : 현재 가리키는 위치가 파일의 끝인 경우 0 을. 아닌 경우에는 0 이 아닌 값을 리턴
<fputs() 함수>
문자열을 대상파일( 지정한 파일 포인터의 파일) 에 기록
* int *fputs( const char *buffer, FILE *fp ) ;
- buffer : 출력할 문자열의 포인터
- fp : 출력할 파일을 가리키는 포인터
#include <stdio.h>
#include <stdlib.h>
void main()
{
FILE *fp ;
fp = fopen( "test.txt", "w" ) ;
fputs( "Hello" , fp ) ; // test.txt 에 Hello 가 저장된다.
fclose( fp ) ;
}
<fgets() 함수>
파일 포인터로부터 원하는 양 만큼의 문자열 데이터를 읽어옴
* char *fgets( char *buffer, int n, FILE *fp ) ;
- buffer : 문자열을 저장하게 되는 영역
- n : 읽어드릴 양
- fp : open 한 파일을 가리키는 포인터
현재 test.txt 파일에는 Hello 가 저장되어 있다.
#include <stdio.h>
#include <stdlib.h>
void main()
{
FILE *fp ;
char str[20] ;
fp = fopen( "test.txt", "r" ) ;
fgets( str, sizeof(str), fp ) ;
printf( "str : %s\n", str ) ; // Hello 출력
fclose( fp ) ;
}
<fread() 함수>
파일로 부터 바이트 단위로 데이터를 읽어들인다.
* size_t fread( void *buffer, size_t size, FILE *fp ) ;
- buffer : 읽어올 데이터를 저장할 메몰리 영역의 포인터
- size : 읽어올 사이즈
- fp : 파일 포인터
- 파일 포인터 fp 에서 size 만큼의 데이터 n 개를 buffer 에 저장
<fwrite() 함수>
파일에 바이트 단위로 데이터 기록
* size_t fwrite( void *buffer, size_t size, size_t n, FILE *fp ) ;
- buffer : 파일에 기록할 데이터가 저장되어 있는 메모리 영역의 포인터
- size : 개별적인 데이터 항목의 크기
- n : 기록할 수
- fp : 파일 포인터
- buffer 에 있는 size 만큼의 데이터 n 개를 파일 포인터 fp 에 기록
#include <stdio.h>
#include <stdlib.h>
struct ADDS{
char name[30] ;
char number[30] ;
} ;
void main()
{
FILE *fp ;
int input, cnt ;
ADDS *Juso ;
while(1)
{
printf( "* [1] 입력 [2] 출력 [3] 종료 *\n" ) ;
printf( "입력 : " ) ;
scanf( "%d", &input ) ;
if( input == 3 ){
printf( "-Good Bye-\n" ) ;
exit( 1 ) ;
}
if( input == 1 ){
printf( "총 몇명 의 주소록을 입력할까요 ?" ) ;
scanf( "%d", &cnt ) ;
Juso = (ADDS*)malloc(sizeof(ADDS)*cnt) ;
fp = fopen( "test.txt", "w" ) ;
for( int i = 0 ; i <cnt ; i++ ){
printf( "이름 : " ) ;
scanf( "%s", Juso[i].name ) ;
printf( "전화번호 : " ) ;
scanf( "%s", Juso[i].number ) ;
}
fwrite( &cnt, sizeof(int), 1, fp ) ; // fwrite cnt 변수값
fwrite( Juso, sizeof(ADDS), cnt, fp ) ; // fwrite Juso 구조체
printf( "저장 완료\n" ) ;
fclose( fp ) ;
free( Juso ) ;
}
if( input == 2 ){
fp = fopen( "test.txt", "r" ) ;
fread( &cnt, sizeof(int), 1, fp ) ;
Juso = (ADDS*)malloc(sizeof(ADDS)*cnt) ;
fread( Juso, sizeof(ADDS), cnt, fp ) ;
printf( "\n" ) ;
for( int i = 0 ; i <cnt ; i++ )
printf( "이름 : %s 전화 : %s\n", Juso[i].name, Juso[i].number ) ;
printf( "\n" ) ;
free( Juso ) ;
fclose( fp ) ;
}
}
}
간단한 주소록 프로그램이다. 소스가 그다지 어렵지 않기 때문에 쉽게 이해 할수 있을 것이다.
<fprintf 와 fscanf>
fprintf 와 fscanf 함수는 printf 와 scanf 함수와 똑같다. 단지 파일이냐 모니터냐의 차이이다. 그리고 앞에 FILE 포인터 변수가 들어간다.
#include <stdio.h>
#include <stdlib.h>
void main()
{
FILE *fp ;
int Index ;
int Data ;
fp = fopen( "test.txt", "w" ) ;
for( Index = 0 ; Index <9 ; Index++ ) // 0 부터 9 까지 test.txt 에 저장
fprintf( fp, "%d\n", Index ) ;
fclose( fp ) ;
fp = fopen( "test.txt", "r" ) ;
for( Index = 0 ; Index <9 ; Index++ ){ // test.txt 에 있는 값을 9개 불러옴.. 0 부터 9 까지 출력
fscanf( fp, "%d", &Data ) ;
printf( "%d\n", Data ) ;
}
fclose( fp ) ;
}
참고 : fscanf()의 경우 입력이 끝나면 -1(EOF)를 리턴한다.
'프로그래머의 길 > C & C++' 카테고리의 다른 글
파일 포인터 관련 함수 ftell(), fseek() (0) | 2007.03.21 |
---|---|
리다이렉션(redirection) 예제 (0) | 2007.03.20 |
콘솔에서 글씨 색과 위치를 변경시켜 보자! (0) | 2007.03.19 |
문자열 함수 strtok 예제 (0) | 2007.03.19 |
동적 할당 관련 함수 malloc, calloc, realloc, free (0) | 2007.03.13 |