C에서, 파일(file)은 디스크 파일에서 터미널 또는 프린터에 이르기까지 어떤 것도 될 수 있다. 열기(open) 연산을 수행하여 특정 스트림과 파일을 연관시킬 수 있다. 파일과 연관된 각 스트림은 FILE형의 파일 제어구조를 가진다.
스트림(논리적 장치)
C에서, 모든 입출력 연산들을 수행하기 위해서 스트림만을 생각한다.
접근할 실제 장치(파일)와는 무관하게 C 프로그래머에게 '일관성 있는 인터페이스'
터미널, 디스크 드라이버, 및 테입 드라이버 등을 포함하여 다양한 장치들과 동작
텍스트 스트림
2진 스트림
표준 스트림은 파일 포인터이다.
stdin
stdout
stderr
size_t // unsinged int
fpos_t // unsinged int
fopen()
대부분의 경우에 파일은 디스크 파일을 의미한다.
만일 파일에 쓰기 위해서 fopen()을 사용하여 파일을 열면, 같은 이름으로 이전에 이미 존재하는 파일은 없어지며 새로운 파일이 생성된다. 만일 같은 이름의 파일이 없다면, 단지 이것이 생성된다. 만일 파일의 끝에 추가하려고 한다면, 모드 "a"를 사용해야 한다. 읽기 연산은 이미 존재하는 파일들에 대해서만 열 수 있다. 만일 이때 그 파일이 존재하지 않으면, 오류가 리턴된다. 마지막으로, 파일이 읽기/쓰기 연산으로 열릴 때 그 파일이 이미 존재하면 삭제되지 않는다. 그러나, 만일 그 파일이 이미 존재하지 않으면, 생성된다.
r // 읽기를 위해 텍스트 파일 열기
rb // 읽기를 위해 2진파일 열기
w // 쓰기를 위해 텍스트 파일 열기
wb // 쓰기를 위해 2진파일 열기
a // 특정 텍스트 파일에 추가하기
ab // 2진 파일에 추가하기
r+ // 읽기/쓰기를 위해서 텍스트 파일 열기
r+b // 읽기/쓰기를 위해서 2진 파일 열기
w+ // 읽기/쓰기를 위해서 텍스트 파일 생성하기
w+b // 읽기/쓰기를 위해서 2진 파일 생성하기
a+ // 읽기/쓰기를 위해서 텍스트 파일을 추가하거나 생성하기
a+b // 읽기/쓰기를 위해서 2진 파일을 추가하거나 생성하기
freopen()
더보기 접기
#include <stdio.h>
void main(void)
{
char str[80];
freopen("OUTPUT", "w", stdout);
printf("Enter a string: ");
gets(str);
printf(str);
}
접기
fclose()
대부분의 경우에, 특정 순간에 열 수 있는 파일들의 수를 운영체제에서 제한하기 때문에, 제한된 파일 수만큼 열렸을 때 또 다른 파일을 열기 전에 하나의 파일을 닫아야 한다. // FOPEN_MAX
ferror()
각 파일 연산은 오류 조건을 설정하기 때문에, ferror()은 각 파일 연산 바로 다음에 호출되어야 한다.
더보기 접기
/* 텍스트 파일에서 탭을 공란수로 대치하고 오류를 검사하는 프로그램 */
#include <stdio.h>
#include <stdlib.h>
#define TAB_SIZE 8
#define IN 0
#define OUT 1
void err(int e);
void main(int argc, char *argv[])
{
FILE *in, *out;
int tab, i;
char ch;
if(argc!=3) {
printf("usage: detab <in> <out>\n");
exit(1);
}
if((in = fopen(argv[1], "rb"))==NULL) {
printf("Cannot open %s.\n", argv[1]);
exit(1);
}
if((out = fopen(argv[2], "wb"))==NULL) {
printf("Cannot open %s.\n", argv[1]);
exit(1);
}
tab = 0;
do {
ch = getc(in);
if(ferror(in)) err(IN);
/* 탭이 있으면, 적당한 공란수로 출력 */
if(ch=='\t') {
for(i=tab; i<8; i++) {
putc(' ', out);
if(ferror(out)) err(OUT);
}
tab = 0;
}
else {
putc(ch, out);
if(ferror(out)) err(OUT);
tab++;
if(tab==TAB_SIZE) tab = 0;
if(ch=='\n' || ch=='\r') tab = 0;
}
} while(!feof(in));
fclose(in);
fclose(out);
}
void err(int e)
{
if(e==IN) printf("Error on input.\n");
else printf("Error on output.\n");
exit(1);
}
접기
feof()
getc()
더보기 접기
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char *argv[])
{
FILE *fp;
char ch;
if(argc!=2) {
printf("You forgot to enter the filename.\n");
exit(1);
}
if((fp=fopen(argv[1], "r"))==NULL) {
printf("Cannot open file.\n");
exit(1);
}
ch = getc(fp); /* 한 문자 읽기 */
while(ch!=EOF) {
putchar(ch); /* 화면에 출력 */
ch = getc(fp);
}
fclose(fp);
}
접기
더보기 접기
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char *argv[])
{
FILE *in, *out;
char ch;
if(argc!=3) {
printf("You forgot to enter a filename.\n");
exit(1);
}
if((in=fopen(argv[1], "rb"))==NULL) {
printf("Cannot open destination file.\n");
exit(1);
}
if((out = fopen(argv[2], "wb")) == NULL) {
printf("Cannot open destination file.\n");
exit(1);
}
/* 다음은 실제로 파일을 복사한다. */
while(!feof(in)) {
ch = getc(in);
if(!feof(in)) putc(ch, out);
}
fclose(in);
fclose(out);
}
접기
fgetc()
putc()
더보기 접기
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char *argv[])
{
FILE *fp;
char ch;
if(argc!=2) {
printf("You forgot to enter the filename.\n");
exit(1);
}
if((fp=fopen(argv[1], "w"))==NULL) {
printf("Cannot open file.\n");
exit(1);
}
do {
ch = getchar();
putc(ch, fp);
} while(ch!='$');
fclose(fp);
}
접기
fputc()
fread()
fwrite()
2진 자료를 위해서 파일을 열기만 하면, fread()와 fwrite()는 어떤 형의 정보도 읽고 쓸 수 있다.
더보기 접기
/* 비문자형 자료를 디스크 파일에 쓰고 이를 다시 읽기 */
#include <stdio.h>
#include <stdlib.h>
void main(void)
{
FILE *fp;
double d = 12.23;
int i = 101;
long l = 123023L;
if((fp=fopen("test", "wb+"))==NULL) {
printf("Cannot open file.\n");
exit(1);
}
fwrite(&d, sizeof(double), 1, fp);
fwrite(&i, sizeof(int), 1, fp);
fwrite(&l, sizeof(long), 1, fp);
rewind(fp);
fread(&d, sizeof(double), 1, fp);
fread(&i, sizeof(int), 1, fp);
fread(&l, sizeof(long), 1, fp);
printf("%f %d %ld", d, i, l);
fclose(fp);
}
접기
fputs()
더보기 접기
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main(void)
{
char str[80];
FILE *fp;
if((fp = fopen("TEST", "w"))==NULL) {
printf("Cannot open file.\n");
exit(1);
}
do {
printf("Enter a string (CR to quit):\n");
gets(str);
strcat(str, "\n"); /* 뉴라인 추가 */
fputs(str, fp);
} while(*str!='\n');
}
접기
fgets()
만일 뉴라인이 읽혀지면, 이것은 (gets() 함수와는 달리) 문자열의 일부가 된다.
gets()
입력받는 문자열 길이를 제한할 수 없어서 보안에 취약
fscanf()
fprintf()
더보기 접기
/* fscanf() - fprintf() 예제 */
#include <stdio.h>
#include <io.h>
#include <stdlib.h>
void main(void)
{
FILE *fp;
char s[80];
int t;
if((fp=fopen("test", "w")) == NULL) {
printf("Cannot open file.\n");
exit(1);
}
printf("Enter a string and a number: ");
fscanf(stdin, "%s%d", s, &t); /* 키보드로부터 읽기 */
fprintf(fp, "%s %d", s, t); /* 파일에 쓰기 */
fclose(fp);
if((fp=fopen("test", "r")) == NULL) {
printf("Cannot open file.\n");
exit(1);
}
fscanf(fp, "%s%d", s, &t); /* 파일에서 읽기 */
fprintf(stdout, "%s %d", s, t); /* 화면에 출력 */
}
접기
fseek()
SEEK_SET
SEEK_CUR
SEEK_END
더보기 접기
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char *argv[])
{
FILE *fp;
if(argc!=3) {
printf("Usage: SEEK filename byte\n");
exit(1);
}
if((fp = fopen(argv[1], "r"))==NULL) {
printf("Cannot open file.\n");
exit(1);
}
if(fseek(fp, atol(argv[2]), SEEK_SET)) {
printf("Seek error.\n");
exit(1);
}
printf("Byte at %ld is %c.\n", atol(argv[2]), getc(fp));
fclose(fp);
}
접기
rewind()
더보기 접기
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main(void)
{
char str[80];
FILE *fp;
if((fp = fopen("TEST", "w+"))==NULL) {
printf("Cannot open file.\n");
exit(1);
}
do {
printf("Enter a string (CR to quit):\n");
gets(str);
strcat(str, "\n"); /* 뉴라인 추가 */
fputs(str, fp);
} while(*str!='\n');
/* 파일 읽고 출력하기 */
rewind(fp); /* 파일 위치 지시자를 파일의 시작으로 재설정 */
while(!feof(fp)) {
fgets(str, 79, fp);
printf(str);
}
}
접기
fflush()
더보기 접기
#include <stdio.h>
#include <errno.h>
#define BUF_SIZE 256
int main (int argc, char *argv [])
{
FILE *in_file, *out_file;
char rec [BUF_SIZE];
size_t bytes_in, bytes_out;
if (argc != 3) {
printf ("Usage: cp file1 file2\n");
return 1;
}
in_file = fopen (argv [1], "rb");
if (in_file == NULL) {
perror (argv [1]);
return 2;
}
out_file = fopen (argv [2], "wb");
if (out_file == NULL) {
perror (argv [2]);
return 3;
}
/* Process the input file a record at a time. */
while ((bytes_in = fread (rec, 1, BUF_SIZE, in_file)) > 0) {
bytes_out = fwrite (rec, 1, bytes_in, out_file);
if (bytes_out != bytes_in) {
perror ("Fatal write error.");
return 4;
}
}
fclose (in_file);
fclose (out_file);
return 0;
}
접기 더보기 접기
void CPractice4_2Dlg::OnButtonOpen()
{
// TODO: Add your control notification handler code here
char Filter[] = "p42 File(*.p42) |*.p42|모든파일(*.*)|*.*|";
CFileDialog pDlg(TRUE, "p42 file(*.p42)", "*.p42", OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, Filter, NULL);
if (pDlg.DoModal() == IDOK)
{
FILE *fp;
fp = fopen (pDlg.GetPathName(), "r");
char strProdName[20], strProdCode[20];
fscanf (fp, "%s\n", strProdName);
m_strProdName = strProdName;
...
fscanf (fp, "%d\n%d\n%d", &m_nUnitCost, &m_nQuantity, &m_nTotalCost);
fclose (fp);
UpdateData(FALSE);
}
}
접기
콘솔 입출력 함수(문자 IO?)
ANSI C 표준은 (커서 위치잡기 같은) 여러 가지 화면 제어 동작을 수행하거나, 또는 그래픽스를 정의하는 함수들은 기계에
따라 매우 다양하기 때문에 포함하지 않고 대신에, 표준 C의 콘솔 입출력 함수들은 TTY-기반의 출력만을 수행한다.
입출력의 방향(stdin, stdout)을 재설정해서 디스크 파일 입출력을 수행할 수도 있다.
#include <stdio.h>
라인-버퍼(line-buffered) 입력
getchar()
입력된 키는 자동적으로 화면으로 반향된다.
putchar()
화면의 현재 커서 위치에 문자를 출력한다.
더보기 접기
#include <stdio.h>
#include <ctype.h>
void main(void)
{
char ch;
printf("Enter some text (type a period to quit).\n");
do {
ch = getchar ();
if(islower(ch)) ch = toupper(ch);
else ch = tolower(ch);
putchar (ch);
} while (ch!='.');
}
접기
#include <conio.h>
interactive
getch()
getche()
화면에 키를 반향
더보기 접기
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
void main(void)
{
char ch;
printf("Enter some text (type a period to quit).\n");
do {
ch = getch ();
if(islower(ch)) ch = toupper(ch);
else ch = tolower(ch);
putchar (ch);
} while (ch!='.');
}
접기 /*
gets()
ENTER를 사용하기 전까지는 백스페이스 키를 이용하여 잘못 입력된 문자들을 수정할 수 있다.
(fgets() 함수와는 달리)캐리지 리턴은 문자열의 일부가 아니다.
*/
puts()
자신의 문자열 인자와 뉴라인를 화면에 출력한다.
printf()를 호출할 때보다 훨씬 부담이 없다.
포맷 변환 등을 할 수 없다.
더보기 접기
#include <stdio.h>
void main(void)
{
char str[80];
gets(str);
puts(str);
}
접기
포맷된 입출력
문자, 문자열, 및 숫자 등을 포함하여 내정된 자료형들에 대해서 IO를 수행
printf()
scanf()
다른 형의 자료를 읽을 때 필드의 분리를 위해서 스페이스, 탭, 및 뉴라인이 사용될 수 있지만, 하나의 문자를 읽을 때, 공란 문자는 다른 어떤 문자들과 유사한 방법으로 읽는다.
공란문자는 공란, 뉴라인, 또는 탭 등이다.
공란 문자는 입력으로부터 하나 또는 그 이상의 공란 문자들을 뛰어넘도록 한다.
비공란 문자는 입력에서 대응하는 문자들을 읽고 삭제된다.
문자열 읽기 - 공란문자를 만날 때까지 입력 문자들을 읽을 수 있다.
참조 사이트: