C Language
파일 및 입출력 스트림
수색…
통사론
- #include <stdio.h> / * 다음 섹션을 사용하려면 이것을 포함 시키십시오. * /
- FILE * fopen (const char * path, const char * mode); / * 지정된 모드 로 경로 의 파일에서 스트림 열기 * /
- FILE * freopen (const char * path, const char * 모드, FILE * stream); / * 지정된 모드 로 경로 에있는 파일의 기존 스트림을 다시여십시오 * /
- int fclose (FILE * stream); / * 열린 스트림 닫기 * /
- size_t fread (void * ptr, size_t size, size_t nmemb, FILE * stream); / * 스트림 에서 각각 size 바이트의 nmemb 요소를 대부분 읽고 ptr에 씁니다. read 요소의 수를 돌려줍니다. * /
- size_t fwrite (const void * ptr, size_t size, size_t nmemb, FILE * stream); / * size 바이트의 nmemb 요소를 ptr 에서 스트림으로 씁니다. 기입해진 요소의 수를 돌려줍니다. * /
- int fseek (FILE * stream, long offset, int whence); / * 스트림의 커서를 whence가 말한 오프셋 에 상대적으로 오프셋 으로 설정하고, 성공하면 0을 반환합니다. * /
- long ftell (FILE * 스트림); / * 스트림의 선두로부터 현재의 커서 위치의 오프셋 (offset)를 돌려줍니다. * /
- void rewind (FILE * stream); / * 커서 위치를 파일의 시작 부분으로 설정하십시오. * /
- int fprintf (FILE * fout, const char * fmt, ...); / * fout에 printf 형식 문자열을 기록합니다 * /
- FILE * stdin; / * 표준 입력 스트림 * /
- FILE * stdout; / * 표준 출력 스트림 * /
- FILE * stderr; / * 표준 오류 스트림 * /
매개 변수
매개 변수 | 세부 |
---|---|
const char * 모드 | 파일 지원 스트림의 열기 모드를 설명하는 문자열. 가능한 값에 대한 설명을보십시오. |
int where | 파일의 처음부터 SEEK_SET , SEEK_END 의 끝에서부터 설정, SEEK_CUR 을 사용하여 현재 커서 값을 기준으로 설정할 수 있습니다. 참고 : SEEK_END 는 휴대 할 수 없습니다. |
비고
모드 문자열 :
fopen()
및 freopen()
모드 문자열은 다음 값 중 하나 일 수 있습니다.
-
"r"
: 커서를 파일의 시작 부분으로 설정하고 읽기 전용 모드로 파일을 엽니 다. -
"r+"
: 커서를 파일의 시작 부분으로 설정하고 읽기 - 쓰기 모드로 파일을 엽니 다. -
"w"
: 쓰기 전용 모드로 파일을 열거 나 만듭니다. 내용은 0 바이트로 잘립니다. 커서는 파일의 시작 부분으로 설정됩니다. -
"w+"
: 내용을 0 바이트로 절단하여 읽기 / 쓰기 모드로 파일을 열거 나 작성하십시오. 커서는 파일의 시작 부분으로 설정됩니다. -
"a"
: 커서를 파일 끝으로 설정하고 쓰기 전용 모드로 파일을 열거 나 작성하십시오. -
"a+"
: 읽기 - 쓰기 모드로 파일을 열거 나 작성하십시오. 이때 읽기 - 커서는 파일의 시작 부분으로 설정하십시오. 그러나 출력은 항상 파일의 끝에 추가됩니다.
이러한 각 파일 모드는 초기 문자 다음에 b
추가 될 수 있습니다 (예 : "rb"
또는 "a+b"
또는 "ab+"
). b
는 차이가있는 시스템에서 파일을 텍스트 파일 대신 2 진 파일로 처리해야 함을의 L합니다. 유닉스 계열 시스템에는 차이가 없다. 그것은 Windows 시스템에서 중요합니다. (또한 Windows fopen
사용하면 '텍스트 파일'을 나타내는 b
대신 명시적인 t
를 사용할 수 있으며 기타 플랫폼 별 옵션도 있습니다.)
-
"wx"
: 쓰기 전용 모드로 텍스트 파일을 만듭니다. 파일이 존재하지 않을 수 있습니다 . -
"wbx"
: 쓰기 전용 모드로 이진 파일을 만듭니다. 파일이 존재하지 않을 수 있습니다 .
x
가있는 경우 x
는 모드 문자열의 마지막 문자 여야합니다.
파일 열기 및 쓰기
#include <stdio.h> /* for perror(), fopen(), fputs() and fclose() */
#include <stdlib.h> /* for the EXIT_* macros */
int main(int argc, char **argv)
{
int e = EXIT_SUCCESS;
/* Get path from argument to main else default to output.txt */
char *path = (argc > 1) ? argv[1] : "output.txt";
/* Open file for writing and obtain file pointer */
FILE *file = fopen(path, "w");
/* Print error message and exit if fopen() failed */
if (!file)
{
perror(path);
return EXIT_FAILURE;
}
/* Writes text to file. Unlike puts(), fputs() does not add a new-line. */
if (fputs("Output in file.\n", file) == EOF)
{
perror(path);
e = EXIT_FAILURE;
}
/* Close file */
if (fclose(file))
{
perror(path);
return EXIT_FAILURE;
}
return e;
}
이 프로그램은 main에 대한 인수에 주어진 이름으로 파일을 열고, 인수가 주어지지 않으면 output.txt
기본값으로 사용합니다. 같은 이름의 파일이 이미 존재하면 그 내용은 삭제되고 파일은 새로운 빈 파일로 취급됩니다. 파일이 아직 존재하지 않으면 fopen()
호출로 파일이 작성됩니다.
어떤 이유로 fopen()
호출이 실패하면 NULL
값을 반환하고 전역 errno
변수 값을 errno
합니다. 이것은 프로그램이 fopen()
호출 후에 반환 된 값을 테스트하고 fopen()
이 실패하면 perror()
사용할 수 있음을 의미합니다.
fopen()
호출이 성공하면 유효한 FILE
포인터를 반환합니다. fclose()
가 호출 될 때까지이 포인터를 사용하여이 파일을 참조 할 수 있습니다.
fputs()
함수는 주어진 텍스트를 열린 파일에 기록하여 파일의 이전 내용을 대체합니다. fopen()
과 마찬가지로 fputs()
함수도 실패 할 경우 errno
값을 설정합니다.이 경우 함수는 실패를 나타내는 EOF
를 반환하지만 그렇지 않은 경우 음수가 아닌 값을 반환합니다.
fclose()
함수는 모든 버퍼를 비우고 파일을 닫은 다음 FILE *
가리키는 메모리를 해제합니다. 반환 값은 fputs()
가 수행하는 것처럼 완료를 나타내며 fputs()
성공하면 '0'을 반환하지만) 실패한 경우 errno
값도 다시 설정합니다.
fprintf
printf
있는 콘솔 에서처럼 fprintf
를 파일에 사용할 수 있습니다. 예를 들어 게임의 승률, 손실 및 동점을 기록하기 위해
/* saves wins, losses and, ties */
void savewlt(FILE *fout, int wins, int losses, int ties)
{
fprintf(fout, "Wins: %d\nTies: %d\nLosses: %d\n", wins, ties, losses);
}
참고 사항 : 일부 시스템 (악의적으로는 Windows)은 대부분의 프로그래머가 "정상"줄 끝이라고 부르는 것을 사용하지 않습니다. UNIX 계열 시스템은 \ n을 사용하여 행을 종료하지만 Windows에서는 \ r (캐리지 리턴) 및 \ n (줄 바꿈) 문자 쌍을 사용합니다. 이 순서는 일반적으로 CRLF라고합니다. 그러나 C를 사용할 때마다 이러한 고도의 플랫폼 종속적 인 세부 사항에 대해 걱정할 필요가 없습니다. \ n의 모든 인스턴스를 올바른 플랫폼 행 끝으로 변환하려면 AC 컴파일러가 필요합니다. 따라서 Windows 컴파일러는 \ n을 \ r \ n으로 변환하지만 UNIX 컴파일러는 그대로 유지합니다.
프로세스 실행
#include <stdio.h>
void print_all(FILE *stream)
{
int c;
while ((c = getc(stream)) != EOF)
putchar(c);
}
int main(void)
{
FILE *stream;
/* call netstat command. netstat is available for Windows and Linux */
if ((stream = popen("netstat", "r")) == NULL)
return 1;
print_all(stream);
pclose(stream);
return 0;
}
이 프로그램은 popen()
)을 통해 프로세스 ( netstat
)를 실행하고 프로세스의 모든 표준 출력을 읽고이를 표준 출력에 반영합니다.
참고 : popen()
은 표준 C 라이브러리 에는 없지만 POSIX C 의 일부입니다.
getline ()을 사용하여 파일에서 행 가져 오기
POSIX C 라이브러리는 getline()
함수를 정의합니다. 이 함수는 라인 내용을 담을 버퍼를 할당하고 새로운 라인, 라인의 문자 수 및 버퍼의 크기를 반환합니다.
example.txt
에서 각 행을 가져 오는 예제 프로그램 :
#include <stdlib.h>
#include <stdio.h>
#define FILENAME "example.txt"
int main(void)
{
/* Open the file for reading */
char *line_buf = NULL;
size_t line_buf_size = 0;
int line_count = 0;
ssize_t line_size;
FILE *fp = fopen(FILENAME, "r");
if (!fp)
{
fprintf(stderr, "Error opening file '%s'\n", FILENAME);
return EXIT_FAILURE;
}
/* Get the first line of the file. */
line_size = getline(&line_buf, &line_buf_size, fp);
/* Loop through until we are done with the file. */
while (line_size >= 0)
{
/* Increment our line count */
line_count++;
/* Show the line details */
printf("line[%06d]: chars=%06zd, buf size=%06zu, contents: %s", line_count,
line_size, line_buf_size, line_buf);
/* Get the next line */
line_size = getline(&line_buf, &line_buf_size, fp);
}
/* Free the allocated line buffer */
free(line_buf);
line_buf = NULL;
/* Close the file now that we are done with it */
fclose(fp);
return EXIT_SUCCESS;
}
입력 파일 example.txt
This is a file
which has
multiple lines
with various indentation,
blank lines
a really long line to show that getline() will reallocate the line buffer if the length of a line is too long to fit in the buffer it has been given,
and punctuation at the end of the lines.
산출
line[000001]: chars=000015, buf size=000016, contents: This is a file
line[000002]: chars=000012, buf size=000016, contents: which has
line[000003]: chars=000015, buf size=000016, contents: multiple lines
line[000004]: chars=000030, buf size=000032, contents: with various indentation,
line[000005]: chars=000012, buf size=000032, contents: blank lines
line[000006]: chars=000001, buf size=000032, contents:
line[000007]: chars=000001, buf size=000032, contents:
line[000008]: chars=000001, buf size=000032, contents:
line[000009]: chars=000150, buf size=000160, contents: a really long line to show that getline() will reallocate the line buffer if the length of a line is too long to fit in the buffer it has been given,
line[000010]: chars=000042, buf size=000160, contents: and punctuation at the end of the lines.
line[000011]: chars=000001, buf size=000160, contents:
이 예에서 getline()
은 처음에는 아무런 버퍼도 할당하지 않고 호출됩니다. 이 첫 번째 호출 중에 getline()
은 버퍼를 할당하고 첫 번째 행을 읽고 그 행의 내용을 새 버퍼에 저장합니다. 후속 호출에서 getline()
은 동일한 버퍼를 업데이트하고 더 이상 전체 행에 적합하지 않을 때만 버퍼를 재 할당합니다. 그런 다음 임시 버퍼는 파일을 완료하면 해제됩니다.
또 다른 옵션은 getdelim()
입니다. 줄 끝 문자를 지정한다는 점을 제외하면 getline()
과 같습니다. 이것은 파일 유형에 대한 행의 마지막 문자가 '\ n'이 아닌 경우에만 필요합니다. 끝나는 멀티 바이트 행 ( "\r\n")
'\ "\r\n")
은 (는) 줄의 마지막 문자이기 때문에 getline()
은 Windows 텍스트 파일에서도 작동합니다.
getline()
구현 예
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <stdint.h>
#if !(defined _POSIX_C_SOURCE)
typedef long int ssize_t;
#endif
/* Only include our version of getline() if the POSIX version isn't available. */
#if !(defined _POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200809L
#if !(defined SSIZE_MAX)
#define SSIZE_MAX (SIZE_MAX >> 1)
#endif
ssize_t getline(char **pline_buf, size_t *pn, FILE *fin)
{
const size_t INITALLOC = 16;
const size_t ALLOCSTEP = 16;
size_t num_read = 0;
/* First check that none of our input pointers are NULL. */
if ((NULL == pline_buf) || (NULL == pn) || (NULL == fin))
{
errno = EINVAL;
return -1;
}
/* If output buffer is NULL, then allocate a buffer. */
if (NULL == *pline_buf)
{
*pline_buf = malloc(INITALLOC);
if (NULL == *pline_buf)
{
/* Can't allocate memory. */
return -1;
}
else
{
/* Note how big the buffer is at this time. */
*pn = INITALLOC;
}
}
/* Step through the file, pulling characters until either a newline or EOF. */
{
int c;
while (EOF != (c = getc(fin)))
{
/* Note we read a character. */
num_read++;
/* Reallocate the buffer if we need more room */
if (num_read >= *pn)
{
size_t n_realloc = *pn + ALLOCSTEP;
char * tmp = realloc(*pline_buf, n_realloc + 1); /* +1 for the trailing NUL. */
if (NULL != tmp)
{
/* Use the new buffer and note the new buffer size. */
*pline_buf = tmp;
*pn = n_realloc;
}
else
{
/* Exit with error and let the caller free the buffer. */
return -1;
}
/* Test for overflow. */
if (SSIZE_MAX < *pn)
{
errno = ERANGE;
return -1;
}
}
/* Add the character to the buffer. */
(*pline_buf)[num_read - 1] = (char) c;
/* Break from the loop if we hit the ending character. */
if (c == '\n')
{
break;
}
}
/* Note if we hit EOF. */
if (EOF == c)
{
errno = 0;
return -1;
}
}
/* Terminate the string by suffixing NUL. */
(*pline_buf)[num_read] = '\0';
return (ssize_t) num_read;
}
#endif
바이너리 파일 열기 및 쓰기
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
result = EXIT_SUCCESS;
char file_name[] = "outbut.bin";
char str[] = "This is a binary file example";
FILE * fp = fopen(file_name, "wb");
if (fp == NULL) /* If an error occurs during the file creation */
{
result = EXIT_FAILURE;
fprintf(stderr, "fopen() failed for '%s'\n", file_name);
}
else
{
size_t element_size = sizeof *str;
size_t elements_to_write = sizeof str;
/* Writes str (_including_ the NUL-terminator) to the binary file. */
size_t elements_written = fwrite(str, element_size, elements_to_write, fp);
if (elements_written != elements_to_write)
{
result = EXIT_FAILURE;
/* This works for >=c99 only, else the z length modifier is unknown. */
fprintf(stderr, "fwrite() failed: wrote only %zu out of %zu elements.\n",
elements_written, elements_to_write);
/* Use this for <c99: *
fprintf(stderr, "fwrite() failed: wrote only %lu out of %lu elements.\n",
(unsigned long) elements_written, (unsigned long) elements_to_write);
*/
}
fclose(fp);
}
return result;
}
이 프로그램은 fwrite
함수를 통해 이진 형식의 텍스트를 작성하여 output.bin
파일에 output.bin
합니다.
같은 이름의 파일이 이미 존재하면 그 내용은 삭제되고 파일은 새로운 빈 파일로 취급됩니다.
이진 스트림은 내부 데이터를 투명하게 기록 할 수있는 정렬 된 문자 시퀀스입니다. 이 모드에서는 해석없이 프로그램과 파일 사이에 바이트가 기록됩니다.
정수를 이식성있게 작성하려면 파일 형식이 크거나 리틀 엔디안 형식인지, 크기 (일반적으로 16, 32 또는 64 비트)가 필요한지 여부를 알아야합니다. 그런 다음 비트 시프 팅 및 마스킹을 사용하여 올바른 순서로 바이트를 쓸 수 있습니다. C의 정수는 2의 보수 표현을 가질 수는 없습니다 (거의 모든 구현이 그렇지만). 다행히도 unsigned 로의 변환 은 2의 보수를 사용하도록 보장됩니다. 따라서 부호있는 정수를 이진 파일에 쓰는 코드는 약간 놀랍습니다.
/* write a 16-bit little endian integer */
int fput16le(int x, FILE *fp)
{
unsigned int rep = x;
int e1, e2;
e1 = fputc(rep & 0xFF, fp);
e2 = fputc((rep >> 8) & 0xFF, fp);
if(e1 == EOF || e2 == EOF)
return EOF;
return 0;
}
다른 함수는 크기와 바이트 순서를 약간 수정하여 동일한 패턴을 따릅니다.
fscanf ()
우리가 텍스트 파일을 가지고 있다고 가정 해보고 몇 가지 요구 사항을 수행하기 위해 그 파일의 모든 단어를 읽고 싶습니다.
file.txt :
This is just
a test file
to be used by fscanf()
이것이 주요 기능입니다.
#include <stdlib.h>
#include <stdio.h>
void printAllWords(FILE *);
int main(void)
{
FILE *fp;
if ((fp = fopen("file.txt", "r")) == NULL) {
perror("Error opening file");
exit(EXIT_FAILURE);
}
printAllWords(fp);
fclose(fp);
return EXIT_SUCCESS;
}
void printAllWords(FILE * fp)
{
char tmp[20];
int i = 1;
while (fscanf(fp, "%19s", tmp) != EOF) {
printf("Word %d: %s\n", i, tmp);
i++;
}
}
출력은 다음과 같습니다.
Word 1: This
Word 2: is
Word 3: just
Word 4: a
Word 5: test
Word 6: file
Word 7: to
Word 8: be
Word 9: used
Word 10: by
Word 11: fscanf()
파일에서 행 읽기
stdio.h
헤더는 fgets()
함수를 정의합니다. 이 함수는 스트림에서 행을 읽고 지정된 문자열에 저장합니다. 이 함수는 n - 1
자 중 하나를 읽거나 개행 문자 ( '\n'
)를 읽거나 파일 끝 (EOF)에 도달하면 스트림에서 텍스트 읽기를 중지합니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_LENGTH 80
int main(int argc, char **argv)
{
char *path;
char line[MAX_LINE_LENGTH] = {0};
unsigned int line_count = 0;
if (argc < 1)
return EXIT_FAILURE;
path = argv[1];
/* Open file */
FILE *file = fopen(path, "r");
if (!file)
{
perror(path);
return EXIT_FAILURE;
}
/* Get each line until there are none left */
while (fgets(line, MAX_LINE_LENGTH, file))
{
/* Print each line */
printf("line[%06d]: %s", ++line_count, line);
/* Add a trailing newline to lines that don't already have one */
if (line[strlen(line) - 1] != '\n')
printf("\n");
}
/* Close file */
if (fclose(file))
{
return EXIT_FAILURE;
perror(path);
}
}
다음 텍스트가 들어있는 파일의 경로 인 인수를 사용하여 프로그램을 호출합니다.
This is a file
which has
multiple lines
with various indentation,
blank lines
a really long line to show that the line will be counted as two lines if the length of a line is too long to fit in the buffer it has been given,
and punctuation at the end of the lines.
결과는 다음과 같습니다.
line[000001]: This is a file
line[000002]: which has
line[000003]: multiple lines
line[000004]: with various indentation,
line[000005]: blank lines
line[000006]:
line[000007]:
line[000008]:
line[000009]: a really long line to show that the line will be counted as two lines if the le
line[000010]: ngth of a line is too long to fit in the buffer it has been given,
line[000011]: and punctuation at the end of the lines.
line[000012]:
이 아주 간단한 예제는 길이가 고정 된 최대 줄 길이를 허용하므로 긴 줄이 실제로 두 줄로 계산됩니다. fgets()
함수는 호출 된 코드가 읽을 줄의 대상으로 사용할 메모리를 제공해야합니다.
POSIX는 getline()
함수를 사용할 수 있도록 해준다. 대신 충분한 메모리가있는 한, 길이에 상관없이 버퍼를 확장하기 위해 내부적으로 메모리를 할당한다.