第五章 标准IO

标准IO不仅仅是unix实现了。

这个库是ISO C标准说明。

Single UNIX Specification对ISO C进行了补充,定义了另外一些接口。

流和FILE对象

第三章围绕fd,而这章函数围绕流

流的定向决定了读写字符是单字节还是多字节-宽

在未定义的流上使用单字节IO函数或者多字节IO函数,则流的定向将被设置单或者宽

只有两个函数可以改变流的定向:freopen和fwide

#include <stdio.h>
#include <wchar.h>
int fwide(FILE *fp,int mode);//流宽定向返回正值,字节定向返回负值,为定向返回0
设定流的定向,前提条件是未被设定流的定向
流可能无效,那么需要前后检查errno

macos的FILE定义
typedef struct __sFILE {
    unsigned char *_p;  /* current position in (some) buffer */
    int _r;     /* read space left for getc() */
    int _w;     /* write space left for putc() */
    short   _flags;     /* flags, below; this FILE is free if 0 */
    short   _file;      /* fileno, if Unix descriptor, else -1 */
    struct  __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
    int _lbfsize;   /* 0 or -_bf._size, for inline putc */

    /* operations */
    void    *_cookie;   /* cookie passed to io functions */
    int (* _Nullable _close)(void *);
    int (* _Nullable _read) (void *, char *, int);
    fpos_t  (* _Nullable _seek) (void *, fpos_t, int);
    int (* _Nullable _write)(void *, const char *, int);

    /* separate buffer for long sequences of ungetc() */
    struct  __sbuf _ub; /* ungetc buffer */
    struct __sFILEX *_extra; /* additions to FILE to not break ABI */
    int _ur;        /* saved _r when _r is counting ungetc data */

    /* tricks to meet minimum requirements even when malloc() fails */
    unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */
    unsigned char _nbuf[1]; /* guarantee a getc() buffer */

    /* separate buffer for fgetln() when line crosses buffer boundary */
    struct  __sbuf _lb; /* buffer for fgetln() */

    /* Unix stdio files get aligned to block boundaries on fseek() */
    int _blksize;   /* stat.st_blksize (may be != _bf._size) */
    fpos_t  _offset;    /* current lseek offset (see WARNING) */
} FILE


/* stdio buffers */
struct __sbuf {
    unsigned char   *_base;
    int     _size;
};

缓冲

全缓冲

满了才flush

行缓冲

遇到换行符就flush,终端是行缓冲

不带缓冲

一般标准错误就是不带缓冲的

更改系统缓冲类型

#include <stdio.h>
void setbuf(FILE *restrict fp,char *restrict buf);//通常全缓冲
int setvbuf(FILE *restrict fp,char *restrict buf,int mode,size_t size);
setvbuf(fp,buf,_IOFBF,BUFSIZE) 相当于 setbuf(fp,buf)
/*
mode:
_IOFBF
_IOLBF
_IONBF
*/
使该流所有未写的数据都被传送至内核
int fflush(FILE *fp);//出错返回EOF

打开流

#include <stdio.h>
FILE *fopen(const char *restrict pathname,const char *restrict type);
FILE *freopen(const char *restrict pathname,const char *restrict type,FILE *restrict stream);
FILE *fdopen(int fd,const char *type);
type:15种不同的值
/*

*/
int fclose(FILE *fp);

fopen:文件名打开

freopen:指定一个流上打开文件

fdopen:fd打开,一般用于管道和网络通信

ps:ISO C并不涉及文件描述符fd,而POSIX.1具有

读和写流

打开流有三种不同类型的非格式化IO

  1. 每次一个字符的IO
  2. 每次一行的IO,可用fgets和fputs
  3. 直接IO(别称:二进制IO),可用fread和fwrite
#include <stdio.h>
输入函数
int getc(FILE *fp);
int fgetc(FILE *fp);
int getchar(void);
/*
getchar等同于getc(stdin)
getc和fgetc:
*/
输出函数
int putc(int c,FILE *fp);
int fputc(int c,FILE *fp);
int putchar(int c);   

3个函数出错和到达文件尾端都是返回相同值,需要下面两个函数做区分

大多数每个流在FILE对象中维护两个标志

出错标志

文件结束标志

#include <stdio.h>
int ferror(FILE *fp);
int feof(FILE *fp);

void clearerr(FILE *fp);

int ungets(int c,FILE *fp);//实质也是写到缓冲区

clearerr可以清除上面两个标志

从流中读取数据,可以用ungetc将字符再压回流中

行IO

#include <stdio.h>
char *fgets(char *restrict buf,int n,FILE *restrict fp);//从指定流读到缓冲区
char *gets(char *buf);//从标准输入读,不推荐用了

int fput(const char *restrict str,FILE *restrict fp);//写到指定流
int puts(const char *str);//还是不用用

二进制IO

#include <stdio.h>
size_t fread(void *restrict ptr,size_t size,size_t nobj,FILE *restrict fp);
size_t fwrite(const void *restrict ptr,size_t size,size_t nobj,FILE *restrict fp);

定位流

ftell,fseek 文件位置放在一个长整型中

ftello,fseeko 使用off_t

fgetpos,fsetpos 使用抽象数据类型fpos_t,非UNIX系统可以使用

#include <stdio.h>
long ftell(FILE *fp);//success:当前文件位置指示 fail:-1L
int fseek(FILE *fp,long offset,int whence);
void rewind(FILE *fp);//将流设置到文件其实位置

off_t ftello(FILE *fp);//与ftell大致相同
int fseeko(FILE *fp,off_t offset,int whence);//与fseek相同

int fgetpos(FILE *restrict fp,fpos_t *restrict pos);
int fsetpos(FILE *fp,const fpos_t *pos);

格式化IO

#include <stdio.h>
int printf
int fprintf
int dprintf
int sprintf
int snprintf

#include <stdio.h>
#include <stdarg.h>
printf变体
int vprintf
int vfprintf
int vdprintf
int vsprintf
int vsnprintf

#include <stdio.h>
int scanf
int fscanf
int sscanf

#include <stdio.h>
#include <stdarg.h>
int vscanf
int vfscanf
int vsscanf

实现

#include <stdio.h>
int fileno(FILE *fp);//对一个流使用,获取这个流的fd

标准IO库最终都要调用第三章的IO历程

临时文件

#inlucde <stdio.h>
char *tmpnam(char *ptr);//产生一个有效路径名字符串
FILE *tmpfile(void);//先产生一个唯一路径名,然后,用此创建一个文件,并立即unlink

#include <stdlib.h>
char *mkdtemp(char *template);//创建目录 

int mkstemp(char *template);//创建名字 返回fd

应该使用tmpfile和mkstemp

内存流

#include <stdio.h>
FILE *fmemopen(void *restrict buf,size_t size,const char *restrict type);
#include <stdio.h>
FILE *open_memstream(char **bufp,size_t *sizep);
#include <wchar.h>
FILE *open_wmemstream(wchar_t **bufp,size_t *sizep);

标准IO的替代软件

快速IO库fio

sfio

mmap

习题

标准IO流怎么使用fsync

先调用fflush( 全都送到内核),再调用fsync(内核写到缓冲区,然后才能写入磁盘,fd可以通过fileno获取)

fgets通常处理行缓冲,自动冲洗的

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容