APUE标准i/o

流和FILE对象

文件IO的所有操作都是基于文件描述符fd,而标准IO的所有操作都是围绕流进行的。当用标准I/O库打开或创建一个文件时,我们使一个流和一个文件关联

标准输入,标准输出,标准出错

对每个进程预定于流三个流,他们是STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO

缓冲

标准I/O库提供缓冲对目的是尽可能对减少使用read/write系统调用的次数,它对每个I/O流自动地进行缓冲管理。
标准I/O提供三种形式的流管理

  • 全缓冲
    在填满缓冲区后才进行I/O,可以手动调用fflush手动缓冲,
  • 行缓冲
    当I/O 中携带遇到换行符是,才进行I/O操作,这允许我们一次写入一个字符。当流涉及终端时,通常使用行缓冲。行缓冲的长度通常是固定的,当超过缓冲区长度后,也会进行I/O操作。任何时候只要通过标准I/O库要求从一个1)不带缓冲的流,或2)行缓冲的流得到输入数据,都将冲洗所有行缓冲输出流。
  • 不缓冲
    不对字符进行缓冲存储,标准错误通常不缓冲。
更改流的缓冲类型
#include<stdio.h>
void setbuf(FILE *restrict fp, char *restrict buf);
int  setvbuf(FILE *restrict fp, char *restrict buf, int mode, size_t size);
    #成功返回0,出错返回非0值
    #关闭缓冲,将buf设置为NULL,
    #setvbuf,可以精确制定缓冲类型,使用mode=(_IOFBF,_IOLBF,_IONBF),如果不缓冲,忽略buf和size参数,如果制定行缓冲和全缓冲,需要制定相应的缓冲区以及长度
int fflush(FILE *fp) #冲洗缓冲区
打开流
  #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 fp)
#在指定流fp上打开指定文件,若该流已打开,则先关闭该流。。若该流已经重定向,则清楚该定向。
 FILE fdopen(int fileds, const char *type)
#获取一个现有文件描述符,,并是一个标准I/O流与该文件描述符结合.常用于由创建管道和网络通信通道函数返回的描述符。
    #成功返回文件指针,出错返回NULL
int fclose(FILE *fp)
    #成功返回0,出错返回EOF 

type通常指 r,w,a...
当以读写类型(r+,w+)打开文件时,具有下列限制

  • 如果中间没有fflush,fseek,fsetpos,rewind,则在输出后不能直接跟随输入
  • 如果中间没有fseek,fsetpos或rewind,或者一个输入操作没有到达文件尾端,则在输入操作后不能直接跟随输出。

在文件关闭之前,会冲洗缓冲区的所有数据,丢弃缓冲区中任何输入数据,如果标准I/O为该流自动分配了一个缓冲区,则释放此缓冲区。
当一个进程正常正常终止时,则所有未写缓冲数据的标准I/O流都会被冲洗,所有打开的I/O流都会被关闭。

读写一个字符

#include<stdio.h>
  int getc(File *fp)
  int fgetc(File *fp)
  int getchar(void)  = getc(stdin)  #从标准输入读
#若成功,则返回下一个字符,出错或达到文件尾端返回EOF
#未区分出错或到达文件尾端,可以使用如下函数
  int ferror(FILE *fp)
  int feof(FILE *fp)
  #条件为真返回非0,否则返回0
  void clearerr(FILE *fp)

每个流在FILE中维护两个标志

  • 出错标志
  • 文件结束标志
    调用clearerr可以清楚这两个标志。
    从流中读取数据后,可以使用ungetc将字符压回流中
#include<stdio.h>
int ungetc(int c, FILE *fp)
  #成功返回c,则出错返回EOF
  # 压送回的流可以被再次读出,但读出字符的顺序与压送回的顺序相反。
  #ungetc会清除该流的文件结束标记

每次一行I/O

#include<stdio.h>
char fgets(char *restrict buf, int n, FILE *fp)
#必须指定缓冲区的长度n,如果没有读到换行符,则读到n-1个字节为止。如果该行长度超过n-1,则fgets会返回不完整的行
char *gets(char *buf) #从标准输入读 
#gets不推荐使用,因为无法指定缓冲区长度,如果写入的内容大于缓冲区长度,会造成缓冲区溢出,写到缓冲区后面的空间中。
#成功返回buf,出错到文件末尾返回NULL
#include<stdio.h>
int fputs(const char* restrict buf, FILE *restrict fp)
#以null终止的字符串写入到指定的流,尾端终止符null不写出。
int puts(const char *str)
# 将以null符终止的字符串写到stdout,null终止符不写出,但是puts又将一个换行符写到stdout
#成功返回非负值,失败返回EOF

疑点:如何处理换行符
尽量使用fgets,fputs

标准I/O的效率

二进制I/O

  #include<stdio.h>
size_t fread(void *restrict ptt, 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)
  #返回读或写的对象数

使用二进制io的时候,只能用于读在同一系统已写过的数据,无法对异构系统数据进行读写。

定位流
long ftell(FILE *fp)
  #返回值:若成功则返回当前未见位置指示,出错返回-1L
int fseek(FILE *fp, long offset, int whence)
  # 返回,若成功返回0,出错返回非0
void rewind(FILE *fp)
格式化I/O
#include<stdio.h>
int printf(const char *restrict format,...);
int fprintf(FILE *restrict fp, const char *restirct format ,...);
#写到指定的流
  #成功返回输出字符数,出错返回负值
int sprintf(char *restrict buf, const char *restrict format,...);
#将格式化字符写送入数组buf中,该函数存在buf指向的缓冲区溢出的风险,调用者有责任确保该缓冲区足够大。
int snprintf(char8restirct buf, size_t n, const char *restrict format,...)
#相较于上面的sprintf,该函数指定了缓冲区长度,如果超过长度的数据,会被丢弃。
  #成功返回存入数组的字符数,出错返回负值

总结:
标准io通过对文件i/o的封装,来进行输入输出操作,在操作对象上,标准io操作的对象是流,文件io操作的是文件描述符。
文件io每次read,write都调用内核中的系统调用,而标准io则通过缓冲区减少系统调用的次数。

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

推荐阅读更多精彩内容

  • 1.1 C标准函数与系统函数 C标准是工作在操作系统之上的。比如要执行C标准函数printf函数,printf会调...
    FlyingReganMian阅读 926评论 0 0
  • 一、Python简介和环境搭建以及pip的安装 4课时实验课主要内容 【Python简介】: Python 是一个...
    _小老虎_阅读 5,618评论 0 10
  • 第三章 文件i/o 3.1引言 不带缓冲的io(unix系统在内核中设有缓冲区,这个不带缓冲意思是用户不自己缓冲)...
    m风满楼阅读 353评论 0 0
  • 一、Linux系统概述 不加引号可理解为宏,直接替换,单引号中特殊字符会被解释为普通字符,双引号中$,,'还是特殊...
    赤果_b4a7阅读 1,403评论 0 2
  • 最近在读unix环境高级编程,每天都会做做笔记! UNIX标准及实现 UNIX编程环境的标准化已经取得了很大进展。...
    MrTrans阅读 397评论 0 1