FMEMOPEN - Linux手册页
Linux程序员手册 第3部分
更新日期: 2020-04-11
名称
fmemopen-以流形式打开内存
语法
#include <stdio.h> FILE *fmemopen(void *buf, size_t size, const char *mode);
glibc的功能测试宏要求(请参阅feature_test_macros(7)):
fmemopen():
- Since glibc 2.10:
- _POSIX_C_SOURCE>= 200809L
- Before glibc 2.10:
- _GNU_SOURCE
说明
fmemopen()函数打开一个流,该流允许通过mode指定的访问。该流允许对buf指向的字符串或内存缓冲区执行I / O。
mode参数指定流上I / O的语义,并且为以下之一:
- r
- 流将打开以供阅读。
- w
- 流将打开以进行写入。
- a
- 附加;打开流进行写入,并将初始缓冲区位置设置为第一个空字节。
- r+
- 打开流以进行读写。
- w+
- 打开流以进行读写。缓冲区内容被截断(即aq \ 0aq放在缓冲区的第一个字节中)。
- a+
- 附加;打开流以进行读取和写入,并将初始缓冲区位置设置为第一个空字节。
流保持当前位置的概念,即当前位置,即执行下一个I / O操作的位置。当前位置由I / O操作隐式更新。可以使用fseek(3)显式更新它,并使用ftell(3)确定它。在除附加模式以外的所有模式下,初始位置均设置为缓冲区的开始。在追加模式下,如果在缓冲区中未找到空字节,则初始位置为size + 1。
如果将buf指定为NULL,则fmemopen()会分配一个大小为字节的缓冲区。这对于希望将数据写入临时缓冲区然后再次读取的应用程序很有用。初始位置设置为缓冲区的开始。当关闭流时,缓冲区自动释放。请注意,调用者无法获取指向此调用分配的临时缓冲区的指针(但请参见open_memstream(3))。
如果buf不为NULL,则它应指向调用方分配的至少len个字节的缓冲区。
当已打开要写入的流被刷新(fflush(3))或关闭(fclose(3))时,如果有空间,则在缓冲区的末尾写入一个空字节。调用者应确保缓冲区中有一个额外的字节(并且大小计入该字节)以允许此操作。
在为读取而打开的流中,缓冲区中的空字节(aq \ 0aq)不会导致读取操作返回文件结束指示。仅当当前缓冲区位置将大小字节提前到缓冲区的开头时,才从缓冲区进行读取将指示文件结束。
写操作发生在当前位置(对于附加模式除外),或在流的当前大小处(对于附加模式)。
尝试将超过大小字节的内容写入缓冲区会导致错误。默认情况下,此类错误仅在刷新stdio缓冲区时才可见(由于没有数据)。通过以下调用禁用缓冲可能对检测输出操作时的错误很有用:
setbuf(stream,NULL);
返回值
成功完成后,fmemopen()返回FILE指针。否则,将返回NULL并将errno设置为指示错误。
版本
fmemopen()在glibc 1.0.x中已经可用。
属性
有关本节中使用的术语的说明,请参见attribute(7)。
Interface | Attribute | Value |
fmemopen(), | Thread safety | MT-Safe |
遵循规范
POSIX.1-2008。 POSIX.1-2001中未指定此功能,并且在其他系统上未广泛使用。
POSIX.1-2008指定应忽略模式下的aqbaq。但是,技术勘误1调整了标准,以允许对此情况进行特定于实现的处理,从而允许对aqbaq进行glibc处理。
备注
没有与此函数返回的文件流关联的文件描述符(即,如果在返回的流上调用fileno(3)将返回错误)。
在2.22版中,删除了二进制模式(请参见下文),修复了fmemopen()实现中的许多长期存在的错误,并为此接口创建了新的版本化符号。
Binary mode
从2.9版到2.21版,fmemopen()的glibc实现支持"二进制"模式,通过将字母aqbaq指定为mode中的第二个字符来启用该模式。在这种模式下,写操作不会隐式添加一个终止的空字节,并且fseek(3)SEEK_END相对于缓冲区的末尾(即size参数指定的值)而不是当前字符串的长度。
一个API错误困扰着二进制模式的实现:要指定二进制模式,aqbaq必须是模式中的第二个字符。因此,例如," wb +"具有期望的效果,但是" w + b"没有。这与fopen(3)对mode的处理不一致。
在glibc 2.22中删除了二进制模式;在mode中指定的aqbaq无效。
BUGS
在2.22之前的glibc版本中,如果将size指定为零,则fmemopen()失败,错误为EINVAL。如果这种情况下成功创建了一个流,然后在第一次读取尝试时返回了文件末尾,那将会更加一致。从2.22版开始,glibc实现提供了该行为。
在2.22之前的glibc版本中,为fmemopen()指定附加模式(" a"或" a +")可将初始缓冲区位置设置为第一个空字节,但是(如果当前位置被重置为非末尾位置)流)不会强制随后的写入追加到流的末尾。此错误已在glibc 2.22中修复。
在2.22之前的glibc版本中,如果fmemopen()的mode参数指定了append(" a"或" a +"),并且size参数未覆盖buf中的空字节,那么根据POSIX.1-2008,初始缓冲区位置应设置为缓冲区结束后的下一个字节。但是,在这种情况下,glibc fmemopen()会将缓冲区位置设置为-1。此错误已在glibc 2.22中修复。
在2.22之前的glibc版本中,当对由fmemopen()创建的流执行以SEEK_END的ncece值调用fseek(3)时,将从流的末尾位置减去偏移量,而不是相加。此错误已在glibc 2.22中修复。
glibc 2.9为fmemopen()添加了"二进制"模式,无声地更改了ABI:以前,fmemopen()在模式下忽略了aqbaq。
示例
下面的程序使用fmemopen()打开输入缓冲区,并使用open_memstream(3)打开动态大小的输出缓冲区。程序扫描其输入字符串(从程序的第一个命令行参数获取)以读取整数,并将这些整数的平方写入输出缓冲区。该程序产生的输出示例如下:
$ ./a.out aq1 23 43aq size=11; ptr=1 529 1849
Program source
#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 aq<num>...aq\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),open_memstream(3)
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。