fopen() — ファイルのオープン

フォーマット

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

言語レベル

ANSI

スレッド・セーフ

はい

説明

fopen() 関数は、filename により指定されるファイルをオープンします。 mode パラメーターは、そのファイルに要求されたアクセス・タイプを指定する文字ストリングです。 mode 変数には、オプションのキーワード・パラメーターが後に続く、位置パラメーターが 1 つ含まれます。

注: プログラムが SYSIFCOPT(*IFSIO) または SYSIFCOPT(*IFS64IO) でコンパイルされている場合で、fopen() が統合ファイル・システムでファイルを作成すると、ファイルの所有者、所有者のグループ、およびパブリックに、ファイルに対する読み取り権限、書き込み権限、および実行権限が与えられます。
位置パラメーターには次の値が可能です。
モード
説明
r
読み取り用にテキスト・ファイルをオープンする ファイルが存在している必要があります。
w
書き込み用にテキスト・ファイルを作成する。所定のファイルが存在している場合、それが論理ファイルでない限り、その内容は破棄されます。
a
ファイルの終わりに書き込む付加モードで、テキスト・ファイルをオープンする。fopen() 関数は、ファイルが存在しておらず、論理ファイルでない場合にファイルを作成します。
r+
読み取りおよび書き込み用にテキスト・ファイルをオープンする。ファイルが存在している必要があります。
w+
読み取りおよび書き込み用にテキスト・ファイルを作成する。所定のファイルが存在している場合、それが論理ファイルでない限り、その内容はクリアされます。
a+
読み取りおよびファイルの終わりでの更新用に、付加モードでテキスト・ファイ ルをオープンする。fopen() 関数は、ファイルが存在していないときにはファイルを作成します。
rb
読み取り用にバイナリー・ファイルをオープンするファイルが存在している必要があります。
wb
書き込み用に空のバイナリー・ファイルを作成する。ファイルが存在している場合、それが論理ファイルでない限り、内容はクリアされます。
ab
ファイルの終わりでの書き込み用に、付加モードでバイナリー・ファイルをオー プンする。fopen 関数は、ファイルが存在していないときにはファイルを作成します。
r+b または rb+
読み取りおよび書き込み用にバイナリー・ファイルをオープンする。ファイルが存在している必要があります。
w+b または wb+
読み取りおよび書き込み用に空のバイナリー・ファイルを作成する。ファイルが存在している場合、それが論理ファイルでない限り、その内容はクリアされます。
a+b または ab+
ファイルの終わりでの書き込み用に、付加モードでバイナリー・ファイルをオー プンする。fopen() 関数は、ファイルが存在していないときにはファイルを作成します。
注:
  1. fopen() 関数は、属性 type=record および ab+, rb+, または wb+ でオープンされたファイルではサポートされていません。
  2. ww+wbw+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 の統合ファイル・システムのトピックにある『ラージ・ファイル・サポート』を参照してください。 2 GB を超える統合ファイル・システムのファイルについては、ご使用のアプリケーションのプログラム・アクセスに 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()

バイナリー・ファイル には、一連の文字が含まれます。バイナリー・ファイルでは、システムは入力または出力の際に制御文字を変換しません。

バイナリー・ファイルが存在していない場合、次のコマンドを使用して作成できます。

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

ファイルを aa+aba+b または ab+ モードでオープンする場合は、すべての書き込み操作はファイルの終わりで行われます。 fseek() 関数または rewind() 関数を使用してファイル・ポインターの位置を変更できますが、書き込み関数は操作を実行する前にファイル・ポインターをファイルの終わりに移動し直します。このアクションは、既存データへの上書きを防ぐためのものです。

更新モード (2 または 3 番目の位置に + を使用して) を指定す る場合は、ファイルの読み書き両方ができます。ただし、読み取りと書き込みの切り替えを行うとき、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 このパラメーターは、順次レコード入出力用にファイルがオープンされることを指定します。ファイルはバイナリー・ファイルとしてオープンされる必要があります。そうでない場合、fopen() 関数は失敗します。読み取り操作と書き込み操作は fread() 関数と fwrite() 関数によって行います。

統合ファイル・システムのキーワード・パラメーター

type=value
指定できる value は、以下の通りです。

record ファイルは順次レコード入出力用にオープンされます。(ファイルはバイナリー・ストリームとしてオープンされる必要があります。)

ccsid=value
ccsid はコード・ページ値に変換されます。 デフォルトとして、コード・ページとしてジョブ CCSID の値を使用します。CCSID とコード・ページ・オプションの両方を指定することはできません。 CCSID オプションは、オペレーティング・システムおよびデータ管理ベースのストリーム入出力との互換性を提供します。
注: 混合データ (データに 1 バイト文字と 2 バイト文字の両方が含まれている) は、テキストのファイル・データ処理モードではサポートされていません。 混合データは、バイナリーのファイル処理モードでサポートされています。

ccsid キーワードを指定する場合は、o_ccsid キーワードやコード・ページ・キーワードを指定できません。

変換されたデータが拡大したり縮小する可能性があるため、データ・サイズや現行のファイル・オフセットを推測することは危険です。 例えば、100 バイトの物理サイズを持つファイルで、アプリケーションがファイルから 100 バイトを読み取った後のファイル・オフセットは 50 しかない場合があります。 含まれている CCSID によっては、ファイル全体を読み取るために、アプリケーションが 200 バイト以上を読み取る必要がある場合があります。このため、ftell()fseek()fgetpos()fsetpos() などのファイル位置決め関数が機能しないことがあります。 これらの関数はエラー ENOTSUP が発生して失敗します。関数の読み取りは、デフォルトのように、バッファリングがオンの場合にも機能しません。 バッファリングをオフにするには、_IONBF キーワードを指定して setvbuf 関数を使用します。

次の 3 つの状態すべてが起こった場合、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 を発生して失敗します。関数の読み取りは、デフォルトのように、バッファリングがオンの場合にも機能しません。 バッファリングをオフにするには、_IONBF キーワードを指定して setvbuf 関数を使用します。

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 により指定されるコード・ページが使用されます。

コード・ページ・キーワードを指定する場合は、ccsid キーワードや o_ccsid キーワードは指定できません。

オープンするファイルが存在しておらず、オープン・モードでファイルを作成するように指定した場合は、ファイルが作成されて計算されたコード・ページでタグ付けされます。 ファイルがすでに存在している場合は、ファイルから読み取られるデータがファイル・コード・ページから計算されたコード・ページに、読み取り操作中に変換されます。ファイルに書き込まれるデータは、計算されたコード・ページにあり、書き込み操作中にファイルのコード・ページに変換されると仮定されます。

crln=value
指定できる value は、以下の通りです。

Y 使用される行の終了文字は、復帰改行文字 [CR] と改行文字 [NL] の組み合わせです。データが読み取られるときに、復帰改行文字 [CR] が string 関数のためにストリップされます。データがファイルに書き込まれるときには、復帰改行文字 [CR] がそれぞれの改行文字 [NL] の前に追加されます。行の終了文字処理は、ファイルがテキスト・モードでオープンされている場合にのみ発生します。 これはデフォルトです。

N 使用される行の終了文字は、改行文字 [NL] のみです。

キーワード・パラメーターは大文字と小文字の区別がなく、コンマで区切ります。

パラメーターが一致しない場合、一般に fopen() 関数は失敗します。

戻り値

fopen() 関数は、オープン・ファイルにアクセスするために使用できる FILE 構造体の型を指すポインターを戻します。
注: ストリーム・ファイル (type = record) を record I/O 関数と一緒に使用する場合、FILE ポインターを RFILE ポインターにキャストする必要があります。

NULL ポインターの戻り値は、エラーを示します。

errno の値は、次のいずれかに設定されます。
意味
EBADMODE
指定されたファイル・モードが無効です。
EBADNAME
指定されたファイル名が無効です。
ECONEVRT
変換エラー。
ENOENT
ファイルまたはライブラリーがありません。
ENOMEM
ストレージ割り振り要求が失敗しました。
ENOTOPEN
ファイルはオープンされていません。
EIOERROR
リカバリー不能な入出力エラーが発生しました。
EIORECERR
リカバリー可能な入出力エラーが発生しました。
ESCANFAILURE
ファイルは走査失敗のマークを付けられました。

fopen() に渡されたモード・ストリングが正しい場合、ファイル・タイプにかかわらず、fopen() は errno を EBADMODE に設定しません。

fopen() に渡されたモード・ストリングが有効でない場合、ファイル・タイプにかかわらず、fopen() は errno を EBADMODE に設定します。

fopen() に渡されたモード・ストリングは正しいが、その指定されたファイル・タイプについては無効な場合は、ファイル・タイプにかかわらず、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);
        }
}