산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Industrial programming >> C 언어

C 파일 입출력: fopen, fprintf, fread, fseek 마스터하기

C 파일 입출력

이 튜토리얼은 C 언어 파일 I/O를 표준 및 바이너리 연산 중심으로 명확하고 실용적인 예제와 함께 안내합니다.

파일은 컴퓨터 저장 장치에 데이터를 장기 보관하기 위한 논리적 컨테이너입니다.


왜 파일을 사용하는가?


파일 유형

C에서는 두 가지 주요 파일 유형을 다룹니다:

  1. 텍스트 파일
  2. 바이너리 파일

텍스트 파일

일반 텍스트 파일(예: .txt)은 모든 텍스트 편집기로 편집 가능합니다. 읽기, 유지보수, 전송이 쉽지만 공간을 더 차지하고 보안성은 낮습니다.

바이너리 파일

바이너리 파일(보통 .bin)은 데이터를 원시 바이트(0과 1)로 저장합니다. 컴팩트하고 사람이 읽을 수 없으며 데이터 무결성과 보안성이 더 좋습니다.


핵심 파일 연산

유형에 관계없이 C 파일 처리는 네 가지 연산을 중심으로 돌아갑니다:

  1. 새 파일 생성
  2. 기존 파일 열기
  3. 파일 닫기
  4. 파일 읽기/쓰기

파일 포인터 준비

모든 파일 연산은 열린 파일을 참조하는 FILE * 포인터가 필요합니다:

FILE *fptr;

파일 열기: 생성과 편집

fopen() 함수(stdio.h에 선언)는 파일을 열고 FILE * 포인터를 반환합니다. 문법:

fptr = fopen("filename", "mode");

사용 예:

fopen("E:\\cprogram\\newprogram.txt", "w");
fopen("E:\\cprogram\\oldprogram.bin", "rb");

설명:

표준 I/O 열기 모드
모드의미파일 없을 때 동작
r읽기 전용 열기NULL 반환
rb바이너리 읽기 전용 열기NULL 반환
w쓰기 전용 열기(덮어쓰기)없으면 생성
wb바이너리 쓰기 전용 열기(덮어쓰기)없으면 생성
a추가 모드 열기없으면 생성
ab바이너리 추가 모드 열기없으면 생성
r+읽기/쓰기NULL 반환
rb+바이너리 읽기/쓰기NULL 반환
w+읽기/쓰기(덮어쓰기)없으면 생성
wb+바이너리 읽기/쓰기(덮어쓰기)없으면 생성
a+읽기/추가없으면 생성
ab+바이너리 읽기/추가없으면 생성

파일 닫기

모든 I/O 연산 후 fclose()로 파일을 닫아 자원을 해제하고 버퍼를 플러시하세요:

fclose(fptr);

텍스트 파일 I/O

텍스트 파일은 fprintf()와 fscanf()로 처리하며, printf()/scanf()의 파일 버전입니다. 첫 인자로 FILE * 포인터가 필요합니다.

예제 1: 텍스트 파일에 쓰기

#include <stdio.h>
#include <stdlib.h>
int main() {
    int num;
    FILE *fptr;
    // OS에 맞게 경로 조정
    fptr = fopen("C:\\program.txt", "w");
    if (fptr == NULL) {
        printf("Error opening file\n");
        exit(EXIT_FAILURE);
    }
    printf("숫자 입력: ");
    scanf("%d", &num);
    fprintf(fptr, "%d", num);
    fclose(fptr);
    return 0;
}

이 프로그램은 사용자로부터 정수를 입력받아 program.txt에 씁니다.

예제 2: 텍스트 파일에서 읽기

#include <stdio.h>
#include <stdlib.h>
int main() {
    int num;
    FILE *fptr;
    fptr = fopen("C:\\program.txt", "r");
    if (fptr == NULL) {
        printf("Error opening file\n");
        exit(EXIT_FAILURE);
    }
    fscanf(fptr, "%d", &num);
    printf("읽은 값: %d\n", num);
    fclose(fptr);
    return 0;
}

첫 예제 실행 후 이 프로그램을 돌리면 저장된 정수가 출력됩니다.

fgetc(), fputc() 같은 추가 유틸리티도 같은 패턴을 따릅니다.


바이너리 파일 I/O

바이너리 파일은 쓰기에 fwrite(), 읽기에 fread()를 사용합니다. 두 함수 모두 네 인자(데이터 포인터, 요소 크기, 요소 개수, FILE * 포인터)를 받습니다.

바이너리 파일에 쓰기

fwrite(addressData, sizeData, numberData, filePointer);

예제 3: fwrite()로 바이너리 파일에 쓰기

#include <stdio.h>
#include <stdlib.h>
struct threeNum {
    int n1, n2, n3;
};
int main() {
    int i;
    struct threeNum num;
    FILE *fptr;
    fptr = fopen("C:\\program.bin", "wb");
    if (fptr == NULL) {
        printf("Error opening file\n");
        exit(EXIT_FAILURE);
    }
    for (i = 1; i < 5; ++i) {
        num.n1 = i;
        num.n2 = 5 * i;
        num.n3 = 5 * i + 1;
        fwrite(&num, sizeof(struct threeNum), 1, fptr);
    }
    fclose(fptr);
    return 0;
}

바이너리 파일에서 읽기

fread() 시그니처는 fwrite()와 동일합니다:

fread(addressData, sizeData, numberData, filePointer);

예제 4: fread()로 바이너리 파일 읽기

#include <stdio.h>
#include <stdlib.h>
struct threeNum {
    int n1, n2, n3;
};
int main() {
    int i;
    struct threeNum num;
    FILE *fptr;
    fptr = fopen("C:\\program.bin", "rb");
    if (fptr == NULL) {
        printf("Error opening file\n");
        exit(EXIT_FAILURE);
    }
    for (i = 1; i < 5; ++i) {
        fread(&num, sizeof(struct threeNum), 1, fptr);
        printf("n1: %d\tn2: %d\tn3: %d\n", num.n1, num.n2, num.n3);
    }
    fclose(fptr);
    return 0;
}

이 프로그램은 예제 3에서 쓴 데이터를 재현합니다.


fseek()로 임의 접근

파일에 많은 레코드가 있을 때 특정 항목까지 순차적으로 이동하는 것은 비효율적입니다. fseek()는 파일 포인터를 임의 위치로 이동시켜 직접 접근을 가능하게 합니다.

문법

fseek(FILE *stream, long int offset, int whence);
fseek() whence 값
상수의미
SEEK_SET파일 처음부터 오프셋.
SEEK_CUR현재 커서 위치부터 오프셋.
SEEK_END파일 끝부터 오프셋.

예제 5: fseek()로 역순 읽기

#include <stdio.h>
#include <stdlib.h>
struct threeNum {
    int n1, n2, n3;
};
int main() {
    int i;
    struct threeNum num;
    FILE *fptr;
    fptr = fopen("C:\\program.bin", "rb");
    if (fptr == NULL) {
        printf("Error opening file\n");
        exit(EXIT_FAILURE);
    }
    // 마지막 레코드로 이동
    fseek(fptr, -sizeof(struct threeNum), SEEK_END);
    for (i = 1; i < 5; ++i) {
        fread(&num, sizeof(struct threeNum), 1, fptr);
        printf("n1: %d\tn2: %d\tn3: %d\n", num.n1, num.n2, num.n3);
        // 현재 위치에서 두 레코드만큼 뒤로(현재 + 하나 더) 이동해 이전 엔트리 읽기
        fseek(fptr, -2 * sizeof(struct threeNum), SEEK_CUR);
    }
    fclose(fptr);
    return 0;
}

이 스니펫은 마지막 레코드부터 시작해 바이너리 파일을 역순으로 순회하는 방법을 보여줍니다.

C 언어

  1. java.io로 Java 파일 작업 마스터하기 – 생성, 읽기, 쓰기 및 삭제
  2. STL 파일 이해하기: 3D 프린팅의 중추
  3. Verilog 파일 I/O 마스터하기: 열기, 읽기, 쓰기, 닫기
  4. C 파일 입출력 완벽 가이드: 열기, 읽기, 쓰기, 위치 제어, 바이너리 처리
  5. C 헤더 파일 이해: 유형, 사용법, 모범 사례
  6. C 언어 에러 처리 마스터하기: 모범 사례와 기법
  7. C++ 파일 입출력 마스터하기: fstream으로 읽고 쓰기
  8. C++ 시그널 처리 마스터하기: 안전한 인터럽트 관리와 깔끔한 프로그램 종료
  9. C# 예외 처리 마스터하기: 전략과 모범 사례
  10. C# 파일 입출력 마스터하기: 스트림, 읽기/쓰기, 고급 파일 작업