fopen() — 파일 열기

형식

#include <stdio.h>
FILE *fopen(const char *filename, const char *mode);

언어 레벨

ANSI

스레드세이프

설명

fopen() 함수는 filename이 지정한 파일을 엽니다. mode 매개변수는 파일에 대해 요청된 액세스 유형을 지정하는 문자 스트링입니다. mode 변수는 선택적 키워드 매개변수가 뒤에 오는 하나의 위치 매개변수를 포함합니다.

참고: 프로그램이 SYSIFCOPT(*IFSIO) 또는 SYSIFCOPT(*IFS64IO)로 컴파일되고 fopen()이 통합 파일 시스템에서 파일을 작성하면 파일 소유자, 소유자의 그룹, 공용에 파일 읽기, 쓰기, 실행 권한이 부여됩니다.
가능한 위치 매개변수 값은 다음과 같습니다.
모드
설명
r
읽기 위해 텍스트 파일을 엽니다. 파일이 있어야 합니다.
w
쓰기 위해 텍스트 파일을 작성합니다. 주어진 파일이 있으면 논리 파일이 아닌 경우 해당 컨텐츠가 영구 삭제됩니다.
a
파일의 끝에서 쓰기 위해 추가 모드에서 텍스트 파일을 엽니다. fopen() 함수는 파일이 없고 논리 파일이 아니면 파일을 작성합니다.
r+
읽고 쓰기 위해 텍스트 파일을 엽니다. 파일이 있어야 합니다.
w+
읽고 쓰기 위해 텍스트 파일을 작성합니다. 주어진 파일이 있으면 논리 파일이 아닌 경우 해당 컨텐츠를 지웁니다.
a+
파일의 끝에서 읽거나 갱신하기 위해 추가 모드에서 텍스트 파일을 엽니다. fopen() 함수는 파일이 없으면 파일을 작성합니다.
rb
읽기 위해 2진 파일을 엽니다. 파일이 있어야 합니다.
wb
쓰기 위해 비어 있는 2진 파일을 작성합니다. 파일이 있으면 논리 파일이 아닌 경우 해당 컨텐츠를 지웁니다.
ab
파일의 끝에서 쓰기 위해 추가 모드에서 2진 파일을 엽니다. fopen 함수는 파일이 없으면 파일을 작성합니다.
r+b 또는 rb+
읽고 쓰기 위해 2진 파일을 엽니다. 파일이 있어야 합니다.
w+b 또는 wb+
읽고 쓰기 위해 비어 있는 2진 파일을 작성합니다. 파일이 있으면 논리 파일이 아닌 경우 해당 컨텐츠를 지웁니다.
a+b 또는 ab+
파일의 끝에서 쓰기 위해 추가 모드에서 2진 파일을 엽니다. fopen() 함수는 파일이 없으면 파일을 작성합니다.
참고:
  1. type=recordab+, rb+ 또는 wb+ 속성으로 열린 파일에는 fopen() 함수가 지원되지 않습니다.
  2. w, w+, wb, w+b, wb+ 매개변수를 주의하여 사용하십시오. 이름이 같은 기존 파일의 데이터가 유실됩니다.
텍스트 파일은 행으로 구성된 인쇄 가능 문자와 제어 문자를 포함합니다. 각 행은 컴파일러에 따라 마지막 행을 제외하고 줄 바꾸기 문자로 끝납니다. 시스템은 출력 텍스트 스트림에서 제어 문자를 삽입하거나 변환할 수 있습니다. fopen() 함수 모드 "a"와 "a+"는 QSYS.LIB 파일 시스템에 사용할 수 없습니다. 모든 모드에서 텍스트 파일에 QSYS.LIB 파일 시스템을 사용하는 경우 구현 제한사항이 있습니다. 파일의 시작을 지나 찾기에 의존하여 텍스트 모드에서 열린 스트림에 대해 작업할 수 없습니다.
참고: fopen()을 사용하여 QSYS.LIB 파일 시스템에서 파일을 작성하는 경우, *LIBL의 라이브러리명 또는 공백을 지정하면 QTEMP 라이브러리에 파일이 작성됩니다.

텍스트 파일이 없으면 다음 명령을 사용하여 작성할 수 있습니다.

CRTSRCPF FILE(MYLIB/MYFILE) RCDLEN(LRECL) MBR(MYMBR) SYSTEM(*FILETYPE)

참고: 텍스트 스트림에 대한 데이터 출력은 입력의 동일한 데이터와 같다고 비교되지 않습니다. QSYS.LIB 파일 시스템은 데이터베이스 파일을 멤버의 디렉토리로 간주합니다. 데이터베이스 파일이 있어야 fopen() 함수를 사용할 때 멤버를 동적으로 작성할 수 있습니다.

통합 파일 시스템의 현재 파일 시스템 한계는 Information Center에서 통합 파일 시스템 주제의 큰 파일 지원을 참조하십시오. 2GB보다 큰 통합 파일 시스템의 파일의 경우, 애플리케이션 프로그램이 64비트 C 런타임 함수에 액세스하도록 허용해야 합니다. 다음 방법을 사용하여 프로그램 액세스를 허용할 수 있습니다.

  • 컴파일 명령에 SYSIFCOPT(*IFS64IO)를 지정하십시오. 원시 C 컴파일러가 _IFS64_IO_를 정의하게 됩니다. 이로 인해 _LARGE_FILES 및 _LARGE_FILE_API 매크로가 정의됩니다.
  • 프로그램 소스에서 또는 컴파일 명령에 DEFINE('_LARGE_FILES')을 지정하여 _LARGE_FILES 매크로를 정의하십시오. 기존의 C 런타임 함수와 코드의 관련 데이터 유형은 모두 해당 64비트 버전에 자동으로 맵핑되거나 재정의됩니다.
  • 프로그램 소스에서 또는 컴파일 명령에 DEFINE('_LARGE_FILE_API')을 지정하여 _LARGE_FILE_API 매크로를 정의하십시오. 이렇게 하면 새 64비트 C 런타임 함수와 데이터 유형 세트가 표시됩니다. 애플리케이션은 사용할 C 런타임 함수(기존 버전과 64비트 버전 둘 다)의 이름을 명시적으로 지정해야 합니다.

64비트 C 런타임 함수는 int fgetpos64(), FILE *fopen64(), FILE *freopen64(), FILE *wfopen64(), int fsetpos64(FILE *, const fpost64_t *), FILE *tmpfile64(), int fseeko(FILE *, off_t, int), int fseeko64(FILE *, off64_t, int), off_t ftello(FILE *), off64_t ftello64()입니다.

2진 파일은 일련의 문자를 포함합니다. 2진 파일의 경우, 시스템은 입력 또는 출력에서 제어 문자를 변환하지 않습니다.

2진 파일이 없으면 다음 명령을 사용하여 작성할 수 있습니다.

CRTPF FILE(MYLIB/MYFILE) RCDLEN(LRECL) MBR(MYMBR) MAXMBRS(*NOMAX) SYSTEM(*FILETYPE)

a, a+, ab, a+b 또는 ab+ 모드로 파일을 열 때 모든 쓰기 조작은 파일의 끝에서 발생합니다. fseek() 함수 또는 rewind() 함수를 사용하여 파일 포인터를 재배치할 수 있긴 하지만 쓰기 함수는 조작을 수행하기 전에 파일 포인터를 파일의 끝으로 다시 이동합니다. 이 조치로 인해 기존의 데이터를 겹쳐쓰지 않습니다.

두 번째 또는 세 번째 위치에서 +를 사용하여 갱신 모드를 지정할 때 파일에서 읽고 파일에 쓸 수 있습니다. 그러나 읽기와 쓰기 간에 전환할 때 fseek(), fsetpos(), rewind() 또는 fflush()와 같은 중개 위치 지정 함수를 포함시켜야 합니다. 파일의 끝을 감지하면 출력이 입력 바로 뒤에 올 수 있습니다.

통합되지 않는 파일 시스템용 키워드 매개변수

blksize=value
레코드의 실제 블록의 최대 길이(바이트)를 지정합니다.
lrecl=value
고정 길이 레코드의 길이(바이트)와 가변 길이 레코드의 최대 길이를 지정합니다.
recfm=value
value는 다음과 같습니다.
F
고정 길이, 블록 해제된 레코드
FB
고정 길이, 블록화된 레코드
V
가변 길이, 블록 해제된 레코드
VB
가변 길이, 블록화된 레코드
VBS
테이프 파일에 대한 가변 길이, 블록화된, 스팬 레코드
VS
테이프 파일에 대한 가변 길이, 블록 해제된, 스팬 레코드
D
테이프 파일의 ASCII D 형식에 대한 가변 길이, 블록 해제된, 스팬되지 않은 레코드
DB
테이프 파일의 ASCII D 형식에 대한 가변 길이, 블록화된, 스팬되지 않은 레코드
U
테이프 파일에 대해 정의되지 않은 형식
FA
프린터 파일에 첫 문자 양식 제어 데이터를 사용하는 고정 길이
참고: CTLCHAR(*FCFC)를 사용하여 파일이 작성된 경우 첫 문자 양식 제어가 사용됩니다. CTLCHAR(*NONE)를 사용하여 파일이 작성된 경우 첫 문자 양식 제어가 사용되지 않습니다.
commit=value
value는 다음과 같습니다.

N 이 매개변수는 이 파일이 커미트 제어 하에서 열리지 않음을 식별합니다. 이는 디폴트입니다.

Y 이 매개변수는 이 파일이 커미트 제어 하에서 열림을 식별합니다.

ccsid=value
오퍼레이팅 시스템이 지원하지 않는 CCSID가 지정된 경우 데이터 관리에서 무시합니다.

컴파일 명령에 LOCALETYPE(*LOCALEUTF)가 지정된 경우 디폴트 값은 현재 로케일 설정을 통해 판별되는 LC_CTYPE CCSID 값입니다. 로케일 설정값에 대한 추가 정보는 setlocale() — 로케일 설정의 내용을 참조하십시오. 컴파일 명령에 LOCALETYPE(*LOCALEUTF)가 지정되지 않은 경우 디폴트 값은 작업 CCSID 값입니다. 파일 CCSID 값에 대한 추가 정보는 파일 CCSID의 내용을 참조하십시오.

arrseq=value
value는 다음과 같습니다.

N 이 매개변수는 이 파일이 작성된 방식으로 처리됨을 식별합니다. 이는 디폴트입니다.

Y 이 매개변수는 이 파일이 도착 순서로 처리됨을 식별합니다.

indicators=value
value는 다음과 같습니다.

N 이 매개변수는 표시장치, ICF 또는 프린터 파일의 인디케이터가 파일 버퍼에 저장됨을 식별합니다. 이는 디폴트입니다.

Y 이 매개변수는 표시장치, ICF 또는 프린터 파일의 인디케이터가 파일 버퍼가 아닌 별도의 인디케이터 영역에 저장됨을 식별합니다. 파일 버퍼는 읽고 쓸 때 시스템이 사용자 프로그램과 오퍼레이팅 시스템으로(에서) 데이터를 전송하는 데 사용하는 영역입니다. ICF 파일을 처리할 때 인디케이터를 별도의 인디케이터 영역에 저장해야 합니다.

type=value
value는 다음과 같습니다.

memory 이 매개변수는 이 파일을 C 프로그램에서만 사용 가능한 메모리 파일로 식별합니다. 이는 디폴트입니다.

record 이 매개변수는 순차 레코드 I/O를 위해 파일을 열도록 지정합니다. 2진 파일로 파일을 열어야 합니다. 그렇지 않으면 fopen() 함수가 실패합니다. 읽기 및 쓰기 조작은 fread() 함수 및 fwrite() 함수로 수행됩니다.

통합 파일 시스템 전용 키워드 매개변수

type=value
value는 다음과 같습니다.

record 순차 레코드 I/O를 위해 파일이 열립니다(2진 스트림으로 파일을 열어야 함).

ccsid=value
ccsid는 코드 페이지 값으로 변환됩니다. 디폴트는 작업 CCSID 값을 코드 페이지로 사용하는 것입니다. CCSID와 codepage 옵션을 둘 다 지정할 수는 없습니다. CCSID 옵션은 오퍼레이팅 시스템 및 데이터 관리 기반 스트림 I/O와의 호환성을 제공합니다.
참고: 텍스트 파일 데이터 처리 모드에는 혼합 데이터(데이터에 1바이트 문자와 2바이트 문자가 둘 다 포함됨)가 지원되지 않습니다. 2진 파일 처리 모드에는 혼합 데이터가 지원됩니다.

ccsid 키워드를 지정하는 경우 o_ccsid 키워드 또는 codepage 키워드를 지정할 수 없습니다.

변환된 데이터의 확장 또는 수축이 가능하기 때문에 데이터 크기와 현재 파일 오프셋을 가정하는 것은 위험합니다. 예를 들어, 파일의 실제 크기는 100바이트이지만 애플리케이션이 파일에서 100바이트를 읽은 후 현재 파일 오프셋은 단지 50입니다. 전체 파일을 읽으려면 애플리케이션이 관련된 CCSID에 따라 200바이트 이상을 읽어야 합니다. 따라서 ftell(), fseek(), fgetpos(), fsetpos()와 같은 파일 위치 지정 함수가 작동하지 않습니다. 이러한 함수가 실패하고 ENOTSUP 오류가 발생합니다. 버퍼링이 설정된 경우(디폴트) 읽기 함수도 작동하지 않습니다. 버퍼링을 설정 해제하려면 setvbuf 함수에 _IONBF 키워드를 사용하십시오.

다음 세 조건이 모두 발생하면 fopen() 함수가 실패하고 ECONVERT 오류가 발생합니다.
  • 파일 데이터 처리 모드가 텍스트입니다.
  • 코드 페이지가 지정되지 않았습니다.
  • 작업의 CCSID가 '혼합 데이터'(데이터에 1바이트 문자와 2바이트 문자가 둘 다 포함됨)입니다.
o_ccsid=value

컴파일 명령에 LOCALETYPE(*LOCALEUTF)가 지정된 경우 디폴트 값은 현재 로케일 설정을 통해 판별되는 LC_CTYPE CCSID 값입니다. 로케일 설정값에 대한 추가 정보는 setlocale() — 로케일 설정의 내용을 참조하십시오. 컴파일 명령에 LOCALETYPE(*LOCALEUTF)가 지정되지 않은 경우 디폴트 값은 작업 CCSID 값입니다. 파일 CCSID 값에 대한 추가 정보는 파일 CCSID의 내용을 참조하십시오.

이 매개변수는 지정된 값이 코드 페이지로 변환되지 않는다는 것을 제외하고 ccsid 매개변수와 유사합니다. 또한 혼합 데이터가 지원됩니다. 파일이 작성되면 지정된 CCSID 태그가 붙습니다. 파일이 이미 있으면 데이터가 파일의 CCSID에서 읽기 조작에 지정된 CCSID로 변환됩니다. 쓰기 조작에서는 데이터가 지정된 CCSID에 있다고 가정하며 파일의 CCSID로 변환됩니다.

변환된 데이터의 확장 또는 수축이 가능하기 때문에 데이터 크기와 현재 파일 오프셋을 가정하는 것은 위험합니다. 예를 들어, 파일의 실제 크기는 100바이트이지만 애플리케이션이 파일에서 100바이트를 읽은 후 현재 파일 오프셋은 단지 50입니다. 전체 파일을 읽으려면 애플리케이션이 관련된 CCSID에 따라 200바이트 이상을 읽어야 합니다. 따라서 ftell(), fseek(), fgetpos(), fsetpos()와 같은 파일 위치 지정 함수가 작동하지 않습니다. 이러한 함수가 실패하고 ENOTSUP이 발생합니다. 버퍼링이 설정된 경우(디폴트) 읽기 함수도 작동하지 않습니다. 버퍼링을 설정 해제하려면 setvbuf 함수에 _IONBF 키워드를 사용하십시오.

o_ccsid를 사용하는 예

/* Create a file that is tagged with CCSID 37 */
if ((fp = fopen("/MYFILE" , "w, o_ccsid=37")) == NULL) {
   printf("Failed to open file with o_ccsid=37\n");
}

fclose(fp);

/* Now reopen the file with CCSID 13488, because your application
 wants to deal with the data in UNICODE */

if ((fp = fopen("/MYFILE" , "r+, o_ccsid=13488")) == NULL) {
   printf("Failed to open file with o_ccsid=13488\n");
}
/* Turn buffering off because read functions do not work when
buffering is on */

if (setbuf(fp, NULL, _IONBF, 0) != 0){
    printf("Unable to turn buffering off\n");
}
/* Because you opened with o_ccsid = 13488, you must provide
all input data as unicode.
If this program is compiled with LOCALETYPE(*LOCALEUCS2),
L constrants will be unicode. */

funcreturn = fputws(L"ABC", fp); /* Write a unicode ABC to the file. */

if (funcreturn < 0) {
   printf("Error with 'fputws' on line %d\n", __LINE__);
}
/* Because the file was tagged with CCSID 37, the unicode ABC was
converted to EBCDIC ABC when it was written to the file. */
codepage=value
value가 지정한 코드 페이지가 사용됩니다.

codepage 키워드를 지정하는 경우 ccsid 키워드 또는 o_ccsid 키워드를 지정할 수 없습니다.

열 파일이 없고 열기 모드가 파일을 작성해야 함을 지정하는 경우에는 파일이 작성되고 연산된 코드 페이지 태그가 붙습니다. 파일이 이미 있으면 파일에서 읽은 데이터가 파일의 코드 페이지에서 읽기 조작 동안 연산된 코드 페이지로 변환됩니다. 파일에 쓰여진 데이터는 연산된 코드 페이지에 있다고 가정하며 쓰기 조작 동안 파일의 코드 페이지로 변환됩니다.

crln=value
value는 다음과 같습니다.

Y 사용될 행 종료자가 캐리지 리턴[CR], 줄 바꾸기[NL] 조합입니다. 데이터를 읽으면 스트링 함수에 대해 모든 캐리지 리턴[CR]이 스트라이프됩니다. 파일에 데이터가 기록되면 캐리지 리턴[CR]이 각 줄 바꾸기[NL] 문자 앞에 추가됩니다. 행 종료자 처리는 파일이 텍스트 모드로 열린 경우에만 발생합니다. 이는 디폴트입니다.

N 사용될 행 종료자가 줄 바꾸기[NL]뿐입니다.

키워드 매개변수는 대소문자를 구분하지 않으며 쉼표로 분리해야 합니다.

매개변수가 일치하지 않으면 일반적으로 fopen() 함수가 실패합니다.

리턴값

fopen() 함수는 열린 파일에 액세스하는 데 사용할 수 있는 FILE 구조 유형을 가리키는 포인터를 리턴합니다.
참고: 스트림 파일(type = record) 레코드 I/O 함수를 사용하려면 RFILE 포인터에 FILE 포인터를 캐스트해야 합니다.

NULL 포인터 리턴값은 오류를 표시합니다.

errno 값을 다음으로 설정할 수 있습니다.
의미
EBADMODE
지정된 파일 모드가 유효하지 않습니다.
EBADNAME
지정된 파일명이 유효하지 않습니다.
ECONEVRT
변환 오류입니다.
ENOENT
파일 또는 라이브러리가 없습니다.
ENOMEM
기억장치 할당 요청에 실패했습니다.
ENOTOPEN
파일이 열려 있지 않습니다.
EIOERROR
회복 불가능한 I/O 오류가 발생했습니다.
EIORECERR
회복 가능한 I/O 오류가 발생했습니다.
ESCANFAILURE
파일에 스캔 실패가 표시되었습니다.

fopen()으로 전달된 mode 스트링이 올바르면 fopen()은 파일 유형에 상관없이 errno를 EBADMODE로 설정하지 않습니다.

fopen()으로 전달된 mode 스트링이 유효하지 않으면 fopen()은 파일 유형에 상관없이 errno를 EBADMODE로 설정합니다.

fopen()으로 전달된 mode 스트링이 올바르지만 해당 특정 파일 유형에 유효하지 않으면 fopen()은 파일 유형에 상관없이 errno를 ENOTOPEN, EIOERROR 또는 EIORECERR로 설정합니다.

이 예는 읽기 위해 파일을 열려고 시도합니다.
#include <stdio.h>
#define  MAX_LEN  60
 
int main(void)
{
   FILE *stream;
   fpos_t pos;
   char line1[MAX_LEN];
   char line2[MAX_LEN];
   char *result;
   char ch;
   int num;
 
   /* The following call opens a text file for reading.   */
   if ((stream = fopen("mylib/myfile", "r")) == NULL)
      printf("Could not open data file\n");
   else if ((result = fgets(line1,MAX_LEN,stream)) != NULL)
           {
            printf("The string read from myfile: %s\n", result);
            fclose(stream);
           }
 
   /* The following call opens a fixed record length file */
   /* for reading and writing.                            */
   if ((stream = fopen("mylib/myfile2", "rb+, lrecl=80,  \
                 blksize=240, recfm=f")) == NULL)
         printf("Could not open data file\n");
   else {
         fgetpos(stream, &pos);
         if (!fread(line2,sizeof(line2),1,stream))
            perror("fread error");
         else printf("1st record read from myfile2: %s\n", line2);
 
         fsetpos(stream, &pos);     /* Reset pointer to start of file */
         fputs(result, stream);     /* The line read from myfile is   */
                                    /* written to myfile2.            */
         fclose(stream);
        }
}