fmemopen函数用法详解
fmemopen函数简介
- 头文件包含
#include <stdio.h>
- 函数定义
FILE *fmemopen(void *buf , size_t size , const char * mode );
fmemopen函数常见使用错误
- 编译错误
warning: implicit declaration of function ‘fmemopen’ [-Wimplicit-function-declaration]
解决办法:包含头文件
#include <stdio.h>
fmemopen函数详细描述
fmemopen ()函数打开一个允许mode 指定的访问的流,该流允许在buf 指向的字符串或内存缓冲区上执行I/O
mode参数指定流上I/O的语义,它是以下内容之一:
- r流打开以供读取。
- w流已打开以进行写入。
- a追加;打开用于写入的流,初始缓冲区位置设置为第一个空字节。
- r+打开流进行读写。
- w+打开流进行读写。缓冲区内容被截断(即(aq\e0(aq放在缓冲区的第一个字节中)。
- a+追加;打开流进行读写,初始缓冲区位置设置为第一个空字节。
流保持当前位置的概念,即执行下一个I/O操作的位置。当前位置由I/O操作隐式更新。它可以使用fseek (3)显式更新,并在除追加之外的所有模式下使用ftell (3)确定,初始位置被设置为缓冲区的开始。在追加模式下,如果在缓冲区中没有找到空字节,那么初始位置是size+1
如果将buf指定为NULL,那么fmemopen ()将分配一个size字节的缓冲区。这对于希望将数据写入临时缓冲区,然后再将其读回的应用程序非常有用。初始位置被设置为缓冲区的开始。当流关闭时,缓冲区将自动释放。请注意,调用方无法获得指向此调用所分配的临时缓冲区的指针(但请参见open_memstream (3))
如果buf不是NULL,那么它应该指向调用方分配的至少有len字节的缓冲区。
当已打开用于写入的流被刷新( fflush (3))或关闭( fclose (3))时,如果有空间,则在缓冲区的末尾写入一个空字节。调用方应该确保缓冲区中有一个额外的字节可用(并且size对该字节进行计数),以允许这样做。
在为读取而打开的流中,缓冲区中的空字节((aq\e0(aq)不会导致读取操作返回文件结束指示。只有当当前缓冲区位置将size字节提前超过缓冲区开始时,从缓冲区读取才会指示文件结束。
写操作要么发生在当前位置(对于追加模式以外的模式),要么发生在流的当前大小(对于追加模式)。
试图向缓冲区写入超过size字节将导致错误。默认情况下,只有在刷新stdio缓冲区时,这样的错误才会(由于没有数据)可见。使用以下调用禁用缓冲对于在输出操作时检测错误可能很有用:
setbuf(流,空);
fmemopen函数返回值
成功完成后,fmemopen ()返回一个FILE指针。否则,返回NULL,并设置errno以指示错误。
fmemopen函数其他说明
没有与此函数返回的文件流相关联的文件描述符(即,如果在返回的流上调用fileno (3)将返回错误)。
在2.22版本中,删除了二进制模式(见下文),修复了fmemopen ()实现中的许多长期存在的错误,并为该接口创建了一个新的版本符号。Binary mode从2.9到2.21版本,fmemopen ()的glibc实现支持“二进制”模式,通过指定字母(aqb(aq)作为mode 中的第二个字符来启用,在此模式下,写入不隐式添加终止空字节,fseek (3) SEEK_END 相对于缓冲区的结尾(即,由size参数指定的值),而不是当前字符串长度。
一个API bug影响了二进制模式的实现:要指定二进制模式,(aqb(aq)必须是mode 中的second字符,因此,例如,“wb+”具有预期的效果,而“w+b”则没有,这与fopen (3)对mode的处理不一致
在glibc2.22中删除了二进制模式;在mode中指定的a(aqb(aq)不起作用。
fmemopen函数使用举例
下面的程序使用fmemopen ()打开输入缓冲区,使用open_memstream (3)打开动态大小的输出缓冲区。程序扫描其输入字符串(取自程序的第一个命令行参数),读取整数,并将这些整数的平方写入输出缓冲区。该程序产生的输出示例如下:
" ./a.out \(aq1 23 43\(aq"
size=11; ptr=1 529 1849
Program source&
#define _GNU_SOURCE
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define handle_error(msg) \e
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\en", 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\en", size, ptr);
free(ptr);
exit(EXIT_SUCCESS);
}
评论区