컴퓨터 언어/C

[C] C언어 9일차 파일 입출력

훈츠 2020. 3. 18. 15:36
반응형

안녕하세요. 훈츠 입니다. 금일은 파일 입출력에 대해 알아보도록 하겠습니다. C, C++ 동일하게 사용된다고 하니 이번기회에 잘 정리해 놓으면 편할듯 싶네요.

파일 입출력 종류

  • 공통점 : 0과 1로 저장된 이진 데이터 
  • 차이점 : 저장하는 방식과 읽는 방식
  • 텍스트 파일 입출력
    • 아스키 코드 값으로 저장 되는 파일
  • 이진 파일 입출력 
    • binary 파일 

파일 입출력 함수 

  • 파일 형식과 상관없이 공용으로 사용하는 함수 
    • FILE *open( const char *filename, const char *mode );
      • int fclose( FILE *stream );
      • int feof( FILE *stream );
      • int fscanf( FILE *s, const char *format, argument... );
      • int fprintf( FILE *s, const char *format, argument... );
  • 텍스트 파일 전용 함수
    • int fgetc ( FILE *stream );
    • int fputc ( int c, FILE *stream );
    • char *fgets( char *string, int n, FILE *stream );
    • int fputs( const char *string, FILE *stream );
  • 이진 파일 전용 함수 
    • size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream);
    • size_t fread( void *buffer, size_t size, size_t count, FILE *stream);
  • FILE 구조체 (데이터 구조만 이해)

  • 파일 열기 
    • FILE *fp 파일 포인터와 fopen() 사용
    • FILE *fopen( const char *filename, const char *mode );
  • 파일 닫기 
    • fclose( FILE *stream );
  • 파일 열기 fopen() 함수의 모드 설정 
    • 입출력 모드 
      • t : 텍스트 파일 모드로 파일 열기 (생략 가능)
      • b : 이진 파일 모드로 파일 열기 
    • 파일 접근 모드 
      • r : 파일 읽기
      • r+ : 파일이 존재할 때만 읽기와 쓰기를 함, 기존 파일이 있는 경우 쓰기에서 덮어쓰기를 함.
        • 파일이 없는 경우는 새로운 파일 생성 못함
      • w : 파일 쓰기, 파일이 없으면 새로 생성하거나 있는 경우는 덮어 쓰기를 함
      • w+ : r+ 와 동일하며 파일이 없으면 새로운 파일 생성
      • a : 기존 파일에 내용을 추가, 파일이 없으면 새로 생성
      • a+ : 파일 읽기, 추가 파일이 없는 경우 새로운 파일 생성 
    • 파일 모드 결합 순서 형식
      • 입출력 모드(r, w, a) + 파일 접근 모드(t, b) + '+'
      • ex) rt, wt, wb, ab+, r, w, w+, rt+ 등

텍스트 파일 읽기, 쓰기 , 추가 예시

파일쓰기 예시

//설정
char _writeMode[] = "w"; //mode 설정 "r , w, a" "r+, w+ , a+"
char *writeMode = &_writeMode; //point 

//연속 문자 읽어오기 예시
FILE* fp;
char cMunja;
	fp = fopen("Text.txt", writeMode); //파일 열기 mode 
    //for 문을 이용해서, 마지막 -1 값이 나오기 전까지 읽기
	for (; ;) {			
		cMunja = fgetc(fp);	//fgetc로 문자 읽어오기 
		if (cMunja == -1) {
			break;
		}
	printf("%c", cMunja); //출력하기 
	}
	printf("\n");
fclose(fp); //항상 열었으면 닫아줘야 한다. 

파일 읽기 예시

//설정
char readMode[] = "r"; //read mode 설정 "r , w, a" "r+, w+ , a+"
char* mode = &readMode; //

//연속 문자 읽어오기 예시
FILE* fp;
char cMunja;
	fp = fopen("Text.txt", mode); //파일 열기 mode 
    //for 문을 이용해서, 마지막 -1 값이 나오기 전까지 읽기
	for (; ;) {			
		cMunja = fgetc(fp);	//fgetc로 문자 읽어오기 
		if (cMunja == -1) {
			break;
		}
	printf("%c", cMunja); //출력하기 
	}
	printf("\n");
fclose(fp); //항상 열었으면 닫아줘야 한다. 

함수 형태로 파일 읽기 쓰기 예시

void FileWrite(char* mode, char* text) {
	FILE* fp;
	fp = fopen("Text.txt", mode);
	fprintf(fp, text);
	fclose(fp);
}

void FileReadAll(char *mode) {
	FILE* fp;
	char cMunja;
	fp = fopen("Text.txt", mode);
	for (; ;) {
		cMunja = fgetc(fp);
		if (cMunja == -1) {
			break;
		}
		printf("%c", cMunja);
	}
	printf("\n");
	fclose(fp);
}
//MODE 구조체 
typedef struct _MODE {
	char* pW;	char* pR;	char* pA;
	char* pWp;	char* pRp;	char* pAp;
	char* input;char* output;
}MODE;

#define R 0
#define W 1
#define A 2
#define RP 3
#define WP 4
#define AP 5

int main() {
	char txt[] = "Test fIle write and read \n";
	char txt1[] = "Message 2 insert\n";
	char txt2[] = "";
	char txt3[] = "";
	char* mode[] = {"r","w","a","r+","w+","a+" };
	
	MODE Mode; //모드 구조체 선언 
	Mode.pR = mode[R]; //각 모드별 할당 'r'
	Mode.pW = mode[W];
	Mode.pA = mode[A];
	Mode.pRp = mode[RP];
	Mode.pWp = mode[WP];
	Mode.pAp = mode[AP];
	char* tText[3];

	tText[0] = &txt;
	tText[1] = &txt1;
	
	FileWrite(Mode.pW, tText[0]);
	FileReadAll(Mode.pR);
	FileWrite(Mode.pW, tText[1]);
	FileReadAll(Mode.pR);
	
	
	_getch();
	return 0;
}

fgets 통해서 범위 지정값 읽거나 fscanf 함수 통해서 데이터 타입에 따른 값 가져오기 

void FileRead(char* mode) {
	FILE* fp;
	char cMunja[100];
	int var;
	fp = fopen("Text.txt", mode);
    
    //file 에서 int value와 char 문자값 읽어오기 
	fscanf(fp, "%d %s", &var, &cMunja);
	printf("%d %s\n", var, cMunja);
	
    //원하는 글자수 읽어오기 
    fgets(cMunja, 5, fp);
	printf("%s \n", cMunja);
	
    fclose(fp);

}

fputs 통해서 범위 지정된 값쓰고 fprintf 함수 통해서 데이터 타입에 따른 값 출력하기

void FileWriteInt(char* mode, char* text) {
	FILE* fp;
	fp = fopen("Text.txt", mode);
	fprintf(fp,"%d %s",333, text); //int 333 출력 
	fclose(fp);
}

이진 파일 입출력 

  • 속성
    • 이진 파일은 사용자 데이터형 크기에 따라 저장 단위가 결정된다. 
  • 이진 파일의 입출력 함수 
    • fwrite() : 임의의 데이터 크기로 개수 만큼 파일에 저장하는 함수 

이진 파일 입출력 예시

typedef struct _DATA {
	int nPlc;
	int nHmi;
	int nDrive;
}DATA;

void FileBwrite(char*mode) {
	FILE* fp;
	DATA Data;

	Data.nPlc = 20;
	Data.nDrive = 30;
	Data.nHmi = 40;

	fp = fopen("Text.txt", mode);
	fwrite(&Data, sizeof(Data), 1, fp); //Data 데이터 크기로 개수만큼 파일로부터 데이터를 씁니다. 
	fclose(fp);
}
void FileBread(char* mode) {
	FILE* fp;
	DATA Data;
	fp = fopen("Text.txt", mode);
	fread(&Data, sizeof(Data), 1, fp);//Data 데이터 크기로 개수만큼 파일로부터 데이터를 읽어옵니다. 
	printf("%d %d %d \n", Data.nPlc, Data.nDrive, Data.nHmi);
	fclose(fp);
}
int main() {
	char* mode[] = {"r","w","a","r+","w+","a+" };
	MODE Mode;
	Mode.pR = mode[R];
	Mode.pW = mode[W];
	char* tText[3];
	FileBwrite(Mode.pW);
	FileBread(Mode.pR);
	_getch();
	return 0;
}

텍스트로 읽으니 아스키코드값의 엉뚱하게 나옵니다.
이진 함수로 읽어오니 Data 값에 입력한 값이 제대로 들어옵니다. 

  • 이진 파일은 암호화가 가능 합니다. 

파일의 임의의 위치에 접근 fseek()함수

  • orgin 을 기준으로 offset 만큼 byte 단위로 파일 포인터로 이동시킵니다.
  • int fseek(FILE *stream, long offset, int origin)
  • orign
    • SEEK_SET -> 파일의 처음으로 이동
    • SEEK_CUR -> 현재 위치
    • SEEK_END -> 파일의 끝으로 이동
void FileFseek(char* mode) {
	FILE* fp;
	char cMunja;
	fp = fopen("Text.txt", mode);
	fseek(fp, 0, SEEK_SET); //파일 처음으로 이동시킨후, 첫번째 글자 "T"
	cMunja = fgetc(fp);
	printf("%c ", cMunja);

	fseek(fp, -1, SEEK_END);//파일 마지막으로 이동시킨후, 마지막-1글자 "D"
	cMunja = fgetc(fp);
	printf("%c ", cMunja);
	fclose(fp);
}

int main() {
	char txt[] = "Test fIle write and reaD";
    char* mode[] = {"r","w","a","r+","w+","a+" };
	
	MODE Mode;
	Mode.pR = mode[R];
	char* tText[3];
	tText[0] = &txt;
	
	FileWrite(Mode.pW, tText[0]);
	FileFseek(Mode.pR); //파일 SEEK

}    
    

T , D 의 출력결과를 확인해보세요.

반응형