C 언어에서 파일을 한 줄씩 읽어 처리하는 방법 완벽 가이드

C 언어에서 파일을 한 줄씩 읽어 반복 처리하는 방법은 텍스트 데이터 처리와 로그 분석, 설정 파일 파싱 등 다양한 작업에 필수적인 기술입니다. 이 기사에서는 파일 열기, 데이터 읽기, 오류 처리, 그리고 응용 사례까지 단계별로 상세히 안내하여 실용적인 파일 처리 능력을 익힐 수 있도록 돕습니다.

목차

C 언어에서 파일 열기와 닫기


파일 처리는 fopenfclose 함수를 사용하여 이루어집니다.

파일 열기: fopen


fopen 함수는 파일을 열고 해당 파일에 대한 포인터를 반환합니다. 사용법은 다음과 같습니다.

FILE *file = fopen("example.txt", "r");
if (file == NULL) {
    printf("파일을 열 수 없습니다.\n");
    return 1;
}
  • 첫 번째 매개변수: 파일 이름(경로 포함)
  • 두 번째 매개변수: 파일 열기 모드
  • "r": 읽기 모드
  • "w": 쓰기 모드(파일 내용 초기화)
  • "a": 추가 모드

파일 닫기: fclose


열린 파일은 사용이 끝난 후 반드시 닫아야 합니다. fclose 함수는 메모리 누수를 방지합니다.

fclose(file);

파일 열기와 닫기 시 주의사항

  • 파일이 제대로 열리지 않을 경우, NULL 포인터가 반환되므로 항상 체크해야 합니다.
  • 열린 파일을 닫지 않으면 시스템 자원이 낭비됩니다.

파일 입출력을 시작하기 전에 올바른 파일 열기와 닫기를 습관화하는 것이 중요합니다.

파일에서 데이터를 한 줄씩 읽는 방법


C 언어에서는 fgets 함수를 사용하여 파일에서 데이터를 한 줄씩 읽을 수 있습니다. 이 방법은 텍스트 파일을 처리하는 데 자주 활용됩니다.

fgets 함수의 기본 사용법


fgets 함수는 지정된 길이만큼의 문자열을 파일에서 읽어 들입니다. 사용 예는 다음과 같습니다.

char buffer[256]; // 한 줄을 저장할 버퍼
FILE *file = fopen("example.txt", "r");

if (file == NULL) {
    printf("파일을 열 수 없습니다.\n");
    return 1;
}

while (fgets(buffer, sizeof(buffer), file)) {
    printf("%s", buffer); // 읽은 줄 출력
}

fclose(file);
  • 매개변수 설명
  • buffer: 데이터를 저장할 문자열 배열
  • sizeof(buffer): 읽을 최대 길이 (버퍼 크기)
  • file: 파일 포인터

fgets 사용 시 주의사항

  • 파일의 한 줄이 버퍼 크기보다 길면, fgets는 데이터를 나눠서 읽습니다.
  • 각 줄의 끝에는 항상 개행 문자(\n)가 포함되므로 이를 처리해야 합니다.

fgets와 파일 포인터의 관계


fgets는 파일 포인터가 EOF(파일 끝)로 이동할 때까지 파일을 읽습니다. 파일 끝에 도달하면 NULL을 반환합니다.

if (fgets(buffer, sizeof(buffer), file) == NULL) {
    printf("파일 끝에 도달했습니다.\n");
}

실제 활용


텍스트 데이터를 줄 단위로 처리해야 하는 경우, fgets는 간단하면서도 강력한 도구입니다. 로그 파일 분석, 설정 파일 읽기 등에서 널리 사용됩니다.

파일 포인터와 에러 처리


파일 처리에서 파일 포인터와 에러 관리는 안정적인 프로그램 작성을 위해 중요합니다. FILE 포인터를 올바르게 사용하고 에러를 적절히 처리하는 방법을 알아봅니다.

파일 포인터의 기본 개념


FILE 포인터는 파일과의 연결 상태를 유지하며, 읽기 또는 쓰기 작업의 시작 위치를 제공합니다.

FILE *file = fopen("example.txt", "r");
if (file == NULL) {
    printf("파일을 열 수 없습니다.\n");
    return 1;
}
  • 파일 포인터 반환값:
  • 성공적으로 파일을 열면 유효한 포인터를 반환합니다.
  • 파일 열기에 실패하면 NULL을 반환합니다.

에러 처리: NULL 확인


파일 열기나 작업이 실패할 경우, NULL 반환값을 확인하여 에러를 처리합니다.

FILE *file = fopen("nonexistent.txt", "r");
if (file == NULL) {
    perror("파일 열기 에러"); // 에러 메시지 출력
    return 1;
}
  • perror 함수: 시스템이 반환하는 에러 메시지를 출력합니다.

파일 읽기 중 에러 처리


파일 읽기 작업 중 오류가 발생할 가능성을 고려해야 합니다. ferror 함수를 사용하여 파일 스트림 상태를 확인할 수 있습니다.

if (ferror(file)) {
    printf("파일 읽기 중 오류가 발생했습니다.\n");
    clearerr(file); // 파일 스트림 상태 초기화
}

EOF(End Of File)와의 차이


파일 끝(EOF)에 도달한 경우와 에러를 구분하는 것이 중요합니다.

if (feof(file)) {
    printf("파일 끝에 도달했습니다.\n");
}
  • EOF: 파일의 끝에 도달했음을 의미하며, 오류가 아닙니다.
  • ferror: 실제 파일 작업 중 오류를 감지합니다.

안전한 파일 처리의 습관

  • 모든 파일 작업 후 반드시 파일을 닫아야 합니다.
  • 에러 상태를 항상 체크하여 적절히 처리합니다.
  • NULL 반환값과 파일 상태 함수(ferror, feof)를 적극 활용합니다.

이러한 방법으로 파일 처리의 안전성과 신뢰성을 높일 수 있습니다.

파일 읽기 중 EOF 처리


파일의 끝(EOF, End Of File)을 올바르게 처리하는 것은 파일 데이터를 효율적으로 읽고 프로그램이 정상적으로 동작하도록 유지하는 데 중요합니다.

EOF의 개념


EOF는 파일의 끝에 도달했음을 나타내는 상태입니다. 파일 읽기 함수는 EOF에 도달하면 작업을 중단하거나 특정 값을 반환합니다. C 언어에서는 feof 함수와 EOF 상수를 사용하여 이를 처리할 수 있습니다.

EOF 확인 방법


feof 함수는 파일 포인터가 EOF 상태인지 확인합니다. EOF 상태가 되면 feof은 참(true)을 반환합니다.

FILE *file = fopen("example.txt", "r");
if (file == NULL) {
    printf("파일을 열 수 없습니다.\n");
    return 1;
}

char buffer[256];
while (fgets(buffer, sizeof(buffer), file)) {
    printf("%s", buffer);
}

if (feof(file)) {
    printf("파일 끝에 도달했습니다.\n");
} else {
    printf("파일 읽기 중 문제가 발생했습니다.\n");
}

fclose(file);

EOF와 반환값 비교


EOF는 파일 끝에 도달했을 때 반환되는 상수입니다. EOF는 일반적으로 -1로 정의되며, 파일 읽기 함수(getc, fgetc 등)는 EOF를 반환하여 종료를 알립니다.

int ch;
while ((ch = fgetc(file)) != EOF) {
    putchar(ch);
}

EOF 처리의 주의점

  1. EOF를 반환하는 함수는 에러를 구별하지 않음
  • feofferror를 함께 사용하여 파일 끝과 에러를 구분해야 합니다.
   if (ferror(file)) {
       printf("파일 읽기 중 오류가 발생했습니다.\n");
   }
  1. EOF는 텍스트 파일에서만 의미가 있음
  • 바이너리 파일에서는 EOF와 유사한 개념이 없으므로 파일 크기를 직접 확인하거나 다른 방법을 사용합니다.

EOF 상태 초기화


파일 작업 후 EOF 상태를 초기화하려면 clearerr 함수를 사용합니다.

clearerr(file);

EOF 처리의 중요성


파일 끝을 명확히 처리하면 불필요한 반복 작업을 방지하고 프로그램이 안정적으로 작동하도록 할 수 있습니다. 특히, 파일 읽기 루프에서 적절한 EOF 처리를 통해 예기치 않은 오류를 예방할 수 있습니다.

파일에서 읽은 데이터의 반복 처리


파일의 데이터를 반복적으로 읽고 처리하는 작업은 데이터 분석, 검색, 변환 등 다양한 응용 분야에서 중요합니다. 이 섹션에서는 반복문을 활용하여 파일 데이터를 효과적으로 처리하는 방법을 설명합니다.

반복문을 사용한 파일 처리


while 루프를 사용하면 파일 끝(EOF)까지 데이터를 반복적으로 읽을 수 있습니다.

FILE *file = fopen("example.txt", "r");
if (file == NULL) {
    printf("파일을 열 수 없습니다.\n");
    return 1;
}

char buffer[256];
while (fgets(buffer, sizeof(buffer), file)) {
    printf("읽은 데이터: %s", buffer);
}

fclose(file);
  • fgets 함수: 각 줄을 읽어 버퍼에 저장합니다.
  • EOF 검사: fgetsNULL을 반환하면 루프가 종료됩니다.

조건문과 함께 데이터 필터링


조건문을 활용하여 특정 데이터를 필터링하거나 선택적으로 처리할 수 있습니다.

while (fgets(buffer, sizeof(buffer), file)) {
    if (strstr(buffer, "keyword")) { // 특정 단어 검색
        printf("키워드 발견: %s", buffer);
    }
}
  • strstr 함수: 버퍼 내 특정 문자열 검색에 사용됩니다.
  • 활용 사례: 로그 파일에서 에러 메시지 추출, 특정 데이터만 처리하기.

반복 처리와 데이터 변환


파일에서 읽은 데이터를 변환하여 새로운 형식으로 저장할 수도 있습니다.

FILE *output = fopen("output.txt", "w");
while (fgets(buffer, sizeof(buffer), file)) {
    fprintf(output, "변환된 데이터: %s", buffer);
}
fclose(output);
  • fprintf 함수: 출력 파일에 포맷팅된 데이터를 기록합니다.
  • 활용 사례: CSV 파일 생성, 데이터 정리 및 변환.

다양한 반복 처리 기술

  1. 데이터 누적: 읽은 데이터를 합산하거나 카운트.
   int line_count = 0;
   while (fgets(buffer, sizeof(buffer), file)) {
       line_count++;
   }
   printf("총 줄 수: %d\n", line_count);
  1. 조건부 처리: 특정 조건을 만족하는 데이터만 계산.
   int keyword_count = 0;
   while (fgets(buffer, sizeof(buffer), file)) {
       if (strstr(buffer, "keyword")) {
           keyword_count++;
       }
   }
   printf("키워드 등장 횟수: %d\n", keyword_count);

효율적인 파일 데이터 처리

  • 최적화된 버퍼 크기를 설정하여 파일 읽기 성능을 개선합니다.
  • 큰 파일의 경우, 메모리 사용량을 최소화하면서 데이터를 처리하는 방법을 고려합니다.
  • 파일 포인터를 항상 닫아 리소스를 적절히 해제합니다.

반복문과 조건문을 활용하면 파일 데이터를 효과적으로 처리할 수 있으며, 이 기법은 텍스트 데이터 분석 및 변환 작업의 핵심입니다.

텍스트 파일 처리 응용 예제


텍스트 파일의 데이터를 다양한 방식으로 처리하는 응용 사례를 살펴봅니다. 이 예제들은 실제로 파일 데이터를 분석하고 가공하는 데 유용합니다.

1. 특정 패턴 검색


파일에서 특정 단어나 패턴을 검색하여 출력하는 프로그램은 로그 분석과 같은 작업에 유용합니다.

FILE *file = fopen("log.txt", "r");
if (file == NULL) {
    printf("파일을 열 수 없습니다.\n");
    return 1;
}

char buffer[256];
while (fgets(buffer, sizeof(buffer), file)) {
    if (strstr(buffer, "ERROR")) { // 'ERROR' 패턴 검색
        printf("에러 발견: %s", buffer);
    }
}

fclose(file);
  • 활용 사례: 시스템 로그에서 에러 메시지 추출, 키워드 기반 텍스트 필터링.

2. 데이터 통계 산출


텍스트 파일의 내용을 분석하여 간단한 통계를 산출할 수 있습니다.

int line_count = 0;
int word_count = 0;
char *token;

while (fgets(buffer, sizeof(buffer), file)) {
    line_count++;
    token = strtok(buffer, " \t\n"); // 단어 분리
    while (token != NULL) {
        word_count++;
        token = strtok(NULL, " \t\n");
    }
}

printf("총 줄 수: %d\n", line_count);
printf("총 단어 수: %d\n", word_count);
  • 활용 사례: 텍스트 파일 내 단어 빈도 분석, 데이터 정리.

3. 파일 데이터 변환 및 출력


파일 데이터를 변환하여 새로운 파일로 저장하는 작업은 데이터 변환에서 중요한 역할을 합니다.

FILE *output = fopen("output.csv", "w");
if (output == NULL) {
    printf("출력 파일을 생성할 수 없습니다.\n");
    return 1;
}

while (fgets(buffer, sizeof(buffer), file)) {
    fprintf(output, "변환된 데이터: %s", buffer);
}

fclose(output);
  • 활용 사례: 텍스트 데이터를 CSV 형식으로 변환, 보고서 생성.

4. 파일 내 특정 값 계산


파일에 포함된 숫자를 읽고 계산하여 유용한 통계를 제공합니다.

int sum = 0, value;
while (fgets(buffer, sizeof(buffer), file)) {
    if (sscanf(buffer, "%d", &value) == 1) { // 숫자 추출
        sum += value;
    }
}

printf("숫자 합계: %d\n", sum);
  • 활용 사례: 데이터 파일의 총합, 평균값 계산.

5. 줄 번호 추가


파일 내용을 읽으며 각 줄에 번호를 추가하여 새로운 파일로 저장합니다.

int line_number = 1;
FILE *output = fopen("numbered.txt", "w");
while (fgets(buffer, sizeof(buffer), file)) {
    fprintf(output, "%d: %s", line_number++, buffer);
}
fclose(output);
  • 활용 사례: 코드 파일 번호 매기기, 데이터 라벨링.

효율적인 응용 사례를 위한 팁

  • 파일 데이터가 크다면 한 번에 전체를 읽기보다는 필요한 부분만 처리합니다.
  • 동적 메모리 할당을 사용하여 버퍼 크기를 조정하면 유연성을 높일 수 있습니다.
  • 파일 데이터 분석 후 시각화 도구와 연계하면 데이터 활용도가 증가합니다.

위 사례들을 통해 파일 데이터를 다양한 방식으로 처리하고 가공할 수 있는 방법을 익힐 수 있습니다.

요약


C 언어에서 파일을 한 줄씩 읽고 처리하는 방법은 데이터 가공과 분석의 기본입니다. fopenfclose로 파일을 열고 닫는 기본 처리에서 시작해, fgets로 데이터를 한 줄씩 읽는 기술, EOF와 에러 처리, 반복문 활용 및 응용 예제까지 살펴보았습니다. 이러한 기법을 익히면 텍스트 데이터 처리와 로그 분석, 데이터 변환 작업을 효율적으로 수행할 수 있습니다.

목차