Provided by: manpages-ja-dev_0.5.0.0.20221215+dfsg-1_all bug

名前

       fmemopen, open_memstream, open_wmemstream - メモリーをストリームとしてオープンする

書式

       #include <stdio.h>

       FILE *fmemopen(void *buf, size_t size, const char *mode);

       FILE *open_memstream(char **ptr, size_t *sizeloc);

       #include <wchar.h>

       FILE *open_wmemstream(wchar_t **ptr, size_t *sizeloc);

   glibc 向けの機能検査マクロの要件 (feature_test_macros(7)  参照):

       fmemopen(), open_memstream(), open_wmemstream():
           glibc 2.10 以降:
               _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L
           glibc 2.10 より前:
               _GNU_SOURCE

説明

       fmemopen()  関数は、ストリームをオープンし、そのストリームに mode で指定されたアクセス許可
       を設定する。 そのストリームを通じて、 buf で指定された文字列やメモリーバッファーへの読み書
       きができる。 このバッファーは少なくとも size バイトの長さでなければならない。

       引き数  modefopen(3) の場合と同じである。 mode で追記モード (append mode) が指定された
       場合、ファイル位置の初期値は バッファー中の 最初のヌルバイト  ('\0')  の位置に設定される。
       それ以外の場合は、ファイル位置の初期値はバッファーの先頭になる。  glibc 2.9 以降では、文字
       'b' を mode の二番目の文字として指定 することができる。 この文字は「バイナリ」モードを指定
       するものである。  このモードでは、書き込み時に文字列終端のヌルバイトが黙って追加 される こ
       とはない。また、 fseek(3) SEEK_END は、文字列の長さからの相対値 ではなく、バッファーの末尾
       (size で指定した値) からの相対値となる。

       書き込み用にオープンされたストリームをフラッシュ (fflush(3))  やクローズ (fclose(3))  した
       時に、 (バッファーに空きがあれば) ヌルバイトがバッファーの末尾に書き込まれる。  このように
       するためには、呼び出し元は バッファーに 1バイト余裕を作る (size にこの 1バイトを含めた値を
       指定する) 必要がある。

       バッファーに size バイトよりたくさん書き込もうとした場合には、エラーとなる。 (デフォルトで
       は、このようなエラーが見えるのは stdio バッファーがフラッシュされた時だけである。 以下の呼
       び出しを使ってバッファーリングを無効にする方法は、  出力操作を行った時点でエラーを検出する
       のに役立つ。

           setbuf(stdream, NULL);

       別の方法としては、  以下のように、  呼び出し側が明示的に  stdio ストリームバッファーとして
       buf を指定し、バッファーの指定時にバッファーのサイズを stdio に教える方法がある。

           setbuffer(stream, buf, size);

       読み出し用にオープンされたストリームでは、 バッファー内にヌルバイト ('\0') があっても 読み
       出し操作がファイル末尾 (end-of-file) を返すことはない。 バッファーからの読み出しでファイル
       末尾が返るのは、 ファイルポインターがバッファーの先頭から size  バイトを越えて先に進もうと
       した場合だけである。

       buf  に NULL が指定された場合、 fmemopen()  は動的に size バイトの長さのバッファーを確保す
       る。 この方法は、一時バッファーにデータの書き込みを行ってから、 その内容を再度読み出すよう
       なアプリケーションで有用である。  このバッファーはストリームがクローズされるときに自動的に
       解放される。 呼び出し元からはこの関数が割り当てた一時バッファーへのポインター値を 知る方法
       は存在しない点に注意 (下記の open_memstream()  も参照)。

       open_memstream()   関数は、バッファーへの書き込み用にストリームをオープンする。 バッファー
       は (malloc(3) を使って) 動的に割り当てられ、必要に応じて自動的に伸長する。  ストリームをク
       ローズした後で、呼び出し元はこのバッファーを free(3) すべきである。

       このストリームが クローズ (fclose(3))  されたりフラッシュ (fflush(3))  された時に、 ptrsizeloc の値はそれぞれバッファーへのポインターとそのサイズに更新される。  これらの値は、呼
       び出し元がそのストリームに新たな書き込みを 行わない場合に限り有効である。 ストリームに書き
       込みを行った際には、これらの変数を参照する前に  ストリームを再度フラッシュしなければならな
       い。

       バッファー末尾のヌルバイトは保持される。 このヌルバイトは sizeloc に格納されるサイズには「
       含まれない」。

       ストリームのファイル位置は fseek(3)  や fseeko(3)  で変更できる。 すでにデータが書き込まれ
       た領域の末尾より先にファイル位置を動かすと、 その間の領域は 0 で埋められる。

       open_wmemstream()   は open_memstream() と同様だが、バイトではなくワイド文字に対して操作を
       行う点が異なる。

返り値

       成功して終了した場合には、 fmemopen(), open_memstream(), open_wmemstream()  は FILE ポイン
       ターを返す。 失敗した場合は、 NULL を返し、 errno にエラーを示す値をセットする。

バージョン

       fmemopen()     と    open_memstream()     は    glibc   1.0.x   ですでに利用可能であった。
       open_wmemstream()  は glibc 2.4 以降で利用可能である。

準拠

       POSIX.1-2008.  これらの関数は POSIX.1-2001 では規定れていないが、 Linux 以外のシステムで広
       く利用可能である。

       POSIX.1-2008   では   mode  の  'b'  は無視されるべきだと規定されて  いる。一方、Technical
       Corrigendum (正誤表) 1 では、mode の 'b'  が指定された場合の扱いは実装依存であることを許容
       するように 標準規格が修正されており、glibc の 'b' の扱いは許されている。

注意

       これらの関数が返すファイルストリームに対応するファイル  ディスクリプターはない (つまり、返
       されたストリームに対して fileno(3) を呼び出すとエラーが返ることになる)。

バグ

       バージョン 2.7 より前の glibc では、 open_memstream() で作成されたストリームの末尾より先に
       ファイル位置を動かしても、 バッファーが伸長されず、 fseek(3)  が失敗し -1 が返る。

       size  に 0 が指定された場合、 fmemopen() はエラー EINVAL で失敗 する。この場合にはストリー
       ムの作成に成功して、最初の読み出しを行った際に EOF (end of file)  が返される方が、ストリー
       ムの扱いの一貫性が増すだろう。  また、  POSIX.1-2008  ではこの場合のエラーは規定されていな
       い。

       fmemopen() に追記モード ("a" や "a+") を指定すると、  ファイル位置の初期値は最初のヌルバイ
       トに設定されるが、(ファイル  オフセットをストリームの末尾以外の位置に再設定した場合)それ以
       降の 書き込みではストリームの末尾への追記が行われる訳ではない。

       fmemopen() の mode 引き数に追記モード ("a" や "a+") を指定し、 size 引き数で指定した範囲の
       buf 内にヌルバイトがない場合、 POSIX.1-2008 では、ファイル位置の初期値はバッファーの末尾の
       直後の バイトに設定すべきとされている。しかし、glibc の fmemopen() では この場合ファイル位
       置は -1 に設定される。

       fmemopen()  でバイナリモードを指定するには、  'b' は mode2 文字目 でなければならない。
       例えば、 "wb+" は意図通りの効果になるが、 "w+b" はそうではない。 これは fopen(3)  の  mode
       の扱いとは異なる。

       glibc   2.9   での   fmemopen()  の「バイナリ」モードの追加は、  ABI  (Application  Binary
       Interface) が黙って変更された。 それ以前の fmemopen() では mode  内の  'b'  は無視されてい
       た。

       このプログラムは  fmemopen()  を使って出力バッファーをオープンし、 open_memstream() を使っ
       て動的にサイズが変化する出力バッファーをオープンしている。 (プログラムの第一コマンドライン
       引き数から取った)   入力文字列を  スキャンして整数を読み込み、これらの整数の二乗を出力バッ
       ファーに書き出す。 このプログラムの実行例は以下のようになる。

           $ ./a.out '1 23 43'
           size=11; ptr=1 529 1849

   プログラムのソース

       #define _GNU_SOURCE
       #include <string.h>
       #include <stdio.h>
       #include <stdlib.h>

       #define handle_error(msg) \
           do { perror(msg); exit(EXIT_FAILURE); } while (0)

       int
       main(int argc, char *argv[])
       {
           FILE *out, *in;
           int v, s;
           size_t size;
           char *ptr;

           if (argc != 2) {
               fprintf(stderr, "Usage: %s <file>\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           in = fmemopen(argv[1], strlen(argv[1]), "r");
           if (in == NULL)
               handle_error("fmemopen");

           out = open_memstream(&ptr, &size);
           if (out == NULL)
               handle_error("open_memstream");

           for (;;) {
               s = fscanf(in, "%d", &v);
               if (s <= 0)
                   break;

               s = fprintf(out, "%d ", v * v);
               if (s == -1)
                   handle_error("fprintf");
           }
           fclose(in);
           fclose(out);
           printf("size=%zu; ptr=%s\n", size, ptr);
           free(ptr);
           exit(EXIT_SUCCESS);
       }

関連項目

       fopen(3), fopencookie(3)

この文書について

       この man ページは Linux man-pages プロジェクトのリリース 3.79 の一部  である。プロジェクト
       の説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。