5.1 引言

标准I/O库处理很多细节,如缓冲区分配,以优化的块长度执行I/O。这些处理用户不必担心如何选择使用正确的块长度

5.2 流和FILE对象

在第3章,所有I/O函数都是围绕文件描述符(file desctriptor)的。而对于标准I/O库,他们的操作是围绕流(stream)进行的。当标准I/O库打开或创建一个文件是,我们以使一个流与一个文件相关联。

流的定向(stream's orientation)决定了所读,写的字符是单字节还是多字节

fwide函数可用于设置流的定向

#include <stdio.h>
#include <wchar.h>
int fwide(FILE *fp, int mode);

(1) mode 为负数,fwide将试图使指定的流是 字节定向

(2) mode为正数,fwide将试图使指定的流是宽定向

(3) mode 为0,fwide将不试图设置流的定向,但返回标示该流定向的值

5.3 标准输入、标准输出和标准错误

对一个进程预定义了3个流,并且这3个流可以自动地被进程使用,他们是标准输入,标准输出和标准错误

5.4 缓冲(Buffering)

标准I/O库提供缓冲的目的是尽可能减少使用read和write调用的次数

标准I/O提供了以下3种类型的缓冲

(1)全缓冲:再填满标准I/O缓冲区后才进行实际I/O操作。对于驻留再磁盘上的文件通常是由标准I/O库实施全缓冲的。标准I/O函数通常调用malloc获得需使用的缓冲区。

(2)行缓冲:当在输入和输出中遇到换行符是,标准I/O库执行I/O操作

(3)不带缓冲:标准I/O库不对字符进行缓冲储存,例如标准I/O函数fputs,就是立即讲字符输出

例如标准错误流,就是不带缓冲的,一旦有错误就尽快输出

大多数系统默认使用一下的类型

(1)标准错误是不带缓冲的

(2)如果指向终端设备的流是行缓冲,其他都是全缓冲

我们可以使用setbuf和setvbuf来改变缓冲类型

#include<stdio.h>
void setbuf(FILE *restrict fp, char *restrict buf);
void setvbuf(FILE *restrict fp, char *restrict buf, int mode, size_t size);

可以使用setbuf函数打开或关闭缓冲机制,为了带缓冲进行I/O,参数buf必须指向一个长度为BUFSIZ的缓冲区。关闭缓冲讲buf设置为NULL

任何时候,我们可以强制冲洗一个流

#include<stdio.h>

int fflush(FILE *fp);

此函数使该流所有未写的数据都传到内核(kernel),作为一种特殊情景,若fp是NULL,则次韩式将导致所有的输出流被冲洗。

5.5 打开流

下列3个函数打开一个标准I/O流

#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);
FILE *fdopen(int fd, const char *type);

这三个函数的区别如下:

(1)fopen函数打开路径名为pathname的一个制定的文件

(2)freopen函数再一个指定的流上打开一个指定的文件,如果该流已经打开,则先将其关闭。若该流已经定向,则使用freopen清除该定向。此函数一般用于讲一个制定的文件打开为一个预定义的流:标准输入、标准输出、标准错误。

(3)fdopen函数区一个已有的文件描述符(file descriptor),并使一个标准的I/O流与该描述符相结合。

type参数指定对该I/O流的读写方式

调用fclose关闭一个打开的流

#include<stdio.h>

int fclose(FILE *fp);

5.6 读和写流

一旦打开了流,则可在3种不同类型的非格式化I/O中进行选择,对其进行读写操作。
(1)每次一个字符的I/O。每次读或者写一个字符,如果流是带缓冲的,则标准I/O函数处理所有缓冲。
(2)每次一行的I/O。如果想一次读或者写一行,使用fgets和fputs。
(3)直接I/O。fread和fwrite支持这种类型的I/O
格式化I/O函数:printf, scanf
1. 输入函数
一下三个函数用于一次读一个字符
#include <stdio.h>
int getc(FILE *fp);
int fgetc(FILE *fp);
int getchar(void);

getc可以实现为宏,fgetc则不能

注意:不管是出错还是到达文件尾,这三个函数都返回同样的值。为了区分两种不同的情况,必须调用ferror或feof
#include <stdio.h>
int ferror(FILE *fp);
int feof(FILE *fp);void clearerr(FILE *fp);

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

#include <stdio.h>
int ungetc(int c, FILE *fp);

2. 输出函数

对于上述的每个输入函数都有一个输出函数
#include<stdio.h>
int putc(int c,FILE *fp);
int fputc(int c, FILE *fp);
int putchar(int c);

同样putchar(c)等同于putc(c,stdout),putc可被实现为宏,而fputc不能

5.7 每次一行I/O

下面每个函数提供每次输入一行的功能
#include <stdio.h>
char *fgets(char *restrict buf, int n, FILE *restrict fp);
char *gets(char *buf);

这两个函数都指定了缓冲区的地址,将读入的行送入其中。gets从标准输入读,而fgets则从指定的流读。

gets是一个不推荐使用的函数。其原因是调用者在使用gets时不能指定缓冲区的长度。这样就可能造成缓冲区一出(如若该行长于缓冲区的长度)
fputs和puts提供每次输出一行的功能
#include<stdio.h>
int fputs(const char *restrict str, FILE *restrict fp);
int puts(const char *str);

函数fputs将一个以null字节终止的字符串写到指定流中,尾端终止符null不写出。

5.8 标准I/O的效率

系统CPU时间几乎相同,原因是所有这些程序对内核提出的读、写请求数基本相同
注意:使用标准I/O例程的一个有点是无需考虑缓冲以及最佳I/O长度的选择。使用fgets需要考虑最大行,但比选择最佳I/O长度方便的多

5.9 二进制I/O

用getc或putc则太慢了。如果使用fputs和fgets,因为fputs遇到null字节时就会停止(因为buf缓冲区就是以null标记结束的),而结构中可能包含null字节,所以不能用来读结构。相似,如果数据中包含null字节或换行符,则fgets特不能正常工作
#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);

这些函数有一下两个常见的用法

(1)读或写一个一个二进制数组,例如将一个浮点数组的第2~5个元素写到一个文件上
float data[10];
if(fwrite(&data[2], sizeof(flaot),4,fp)!=4)err_sys("fwrite eerror");

size为每个数组元素的长度,nobj为欲写的元素的个数

(2)读或写一个结构

struct {short count;long tatal;char name[NAMESIZE];
}item;
if(fwrite(&item, sizeof(item), 1, fp)!=1)err_sys("fwrite error");

5.10 定位流

有三种方法定位标准I/O流

(1)ftell和fseek函数,但它们都假定文件的位置可以存放在一个长整型中

#include <stdio.h>
long ftell (FILE *fp);
int fseek(FILE *fp, long offset, int whence);
void rewind(FILE *fp);

ftell用于二进制文件时,其返回值就是这种字节位置

为了用fseek定位一个二进制文件,必须制定一个字节offset,以及解释这种偏移量的方式。whence的值lseek函数的相同:

SEEK_SET:表示从文件的起始位置开始

SEEK_CUP:表示从当前文件位置开始

SEEK_END:表示从文件的尾端开始

使用rewind函数也可以讲一个流设置到起始位置

(2)ftello和fseeko函数使文件偏移量可以不必为长整型,使用off_t数据类型代替

#include <stdio.h>
off_t ftello(FILE *fp);
int fseeko(FILE *fp, off_t offset, int whence);

除了用off_t替换了long剩下的和ftell一样

(3)fgetpos和fsetpos函数。它们使用一个抽象数据类型fpos_t记录文件的位置。这种数据类型可以更具需要定义为一个足够大的数,用以记录文件的位置

#include <stdio.h>
int fgetpos(FILE *restrict fp, fpos_t *restrict pos);
int fsetpos(FILE *fp, const fpos_t *pos);

fgetpos将文件位置指示器的当前值存入由pos指向的对象中。以后调用fsetpos时,可以使用此值将流重新定位到该位置

5.11 格式化I/O

1.格式化输出

格式化输出是由5个printf函数来处理
#include <stdio.h>
int printf(const char *restrcit format, ...);
int fprintf(FILE *restrict fp, const char *restrict format, ...);
int dprintf(int fd, const char *restrict format, ...);
int sprintf(char *restrict buf, const char *restrict format);
int snprintf(char *restrict buf, size_t n, const char *restrict);

printf将格式化数据写到标准输出。

fprintf写到指定的流中
dprintf写到指定的文件描述符
sprintf讲指定格式写到数组buf中,再该数组的尾端自动加一个null字节,但该字节不包含再返回值中
notice:sprintf函数可能造成由buf指向的缓冲区的溢出。调用必须确保缓冲区足够大
为了解决这个问题引入了snprintf函数,再该函数,缓冲区长度是一个显示参数。大于缓冲区长度则截断(truncated)

2.格式化输入

执行格式化输入处理的是三个scanf函数
#include<stdio.h>
int scanf(const char *restrict format, ...);
init fscanf(FILE *restrict fp, const char *restrict format);
int sscanf(const char *restrict buf, const char *restrict format);

5.12 实现细节

在UNIX中,标准I/O库最终都要调用文件描述符的相关操作函数。每个标准I/O流都有一个与其相关联的文件描述符,可以对一个流调用fileno函数以获得其描述符
#include<stdio.h>
int fileno(FILE *fp);

如果要调用dup(获得新的文件描述符)或fcntl(改变已经打开的文件的属性)等函数,则需要此函数

5.13 临时文件

IOS C标准I/O库提供了两个函数以帮助创建临时文件

#include <stdio.h>
char *tmpnam(char *ptr);
FILE *temfile(void);

tmpnam函数产生一个与现有的文件名不同的一个有效路径名字字符串

若ptr是NULL,则产生的路径名存放再一个静态区中,指向该静态去的指针作为函数值返回

若ptr不是NULL,则认为它应该是指向长度至少是L_tmpnam个字符的数组,所产生的路径名存放在该数组中

对一个文件解除链接并不删除其内容,关闭该文件是才删除内容

5.14 内存流

用于对内存缓冲区的字符串进行操作
有3个函数可以用于内存流打开,fmemopen

#include <stdio.h>
FILE *fmemopen(void *restrict buf, size_t size, const char *restrict type);

fmemopen函数允许调用者提供缓冲区用于内存流

buf指向缓冲区的开始位置
size参数指定了缓冲区大小的字节数
type控制如何使用流

UNIX环境高级编程之第5章:标准I/O库相关推荐

  1. UNIX 环境高级编程总结——第五章 标准I/O 库

    5.1 流和 FILE 对象 对于标准 I/O 库,它们的操作则是围绕流(stream)进行的. 当打开一个流时,标准 I/O 函数 fopen 返回一个指向 FILE 对象的指针. 为了引用一个流, ...

  2. UNIX环境高级编程之第4章:文件和文件夹-习题

    4.1 stat函数是尾随符号链接的,所以用stat替换lstat不会显示符号链接的信息 4.2 在一个目录下先再shell中输入umask shell进程再进行创建文件的操作.其权限抖都会被屏蔽 4 ...

  3. unix环境高级编程之 read与write 函数详解

    学习记录:unix环境高级编程之 read 与write  函数详解 备注:本博文非本人所写,本人觉得此文讲的非常地道通俗易懂,所以摘录在此以方便以后再次查看 read函数从打开的设备或文件中读取数据 ...

  4. UNIX环境高级编程源码

    UNIX环境高级编程源码 一.下载源码 利用wget命令下载源码,源码地址http://apuebook.com/src.3e.tar.gz 可以在服务器的根目录下创建文件夹,mkdir 1.mkdi ...

  5. 《Unix环境高级编程》Note——第一章基础知识

    文章目录 第一章 Unix基础知识 1.引言 2.Unix体系结构 3.登录 4.文件和目录 5.输入和输出 6.程序和进程 7.出错处理 8.用户标识 9.信号 10.时间值 11.系统调用和库函数 ...

  6. UNIX环境高级编程(屏幕打印和inet_ntoa输出异常问题)

    一.来回在屏幕和文件之间打印 在网上没找到在屏幕和文件来回打印的方法,翻了下UNIX环境高级编,里面有个freopen用于在一个指定的流上打开一个指定的文件,如果要将标准输出打印到文件,需要调用该函数 ...

  7. python flask高级编程之restful_('Python Flask高级编程之RESTFul API前后端分离精讲',),全套视频教程学习资料通过百度云网盘下载...

    资源详情 r n t某课网好评度100%的Python Flask高级编程之RESTFul API前后端分离精讲 r n t t t第1章 随便聊聊 r n t t t聊聊Flask与Django,聊 ...

  8. 《UNIX环境高级编程(第3版)》——1.7 出错处理

    本节书摘来自异步社区<UNIX环境高级编程(第3版)>一书中的第1章,第1.7节,作者:[美]W. Richard Stevens , Stephen A.Rago著,更多章节内容可以访问 ...

  9. unix环境高级编程 pdf_UNIX系统编程宝典,每一本都值得程序员珍藏

    这几本UNIX系统编程宝典,重印无数次,几代程序员都视如珍宝的几本书,小编在出版圈里快十年了,见证了这本书图灵版.异步社区版的出版.营销,对这套书倾注了一定的感情.今天继续分享给你们,好书总会有人还不 ...

  10. 开发日记-20190822 关键词 读书笔记《Unix环境高级编程(第二版)》《掌控习惯》DAY 2

    Preface 话说,昨天开始尝试着去改变自己,从基础的习惯开始,11:30准时睡觉,平时差不多12:30才睡觉.按理说,比平时早了一个小时睡觉吧,然后我就把闹钟提前了45分钟,想着还能比平常多睡15 ...

最新文章

  1. 瑞星杀毒软件所有监控已禁用!
  2. 两分公支的IPSec***流量走总部测试
  3. product text的language dropdown list里 没有对应语言的问题
  4. 提高篇 第五部分 动态规划 第2章 树型动态规划
  5. Java对json遍历_如何遍历Java中的json对象
  6. java框架----mybatis的使用(一)
  7. exchange创建邮箱组_Exchange批量创建用户组及启用通讯组邮箱-阿里云开发者社区...
  8. ON DELETE CASCADE和ON UPDATE CASCADE
  9. java jdk 文档下载_Java帮助文档 JDK全系列 官方中英下载地址
  10. 解决Windows不在第一分区时变色龙引导问题
  11. 基于单片机的超市储物柜设计_一种超市用储物柜的制作方法
  12. 在WINDOWS下的Services.mscl里有好几个ORACLE的SERVICES的一些作用
  13. C# winform 一个简单的类的方法的封装与调用
  14. 搞定计算机网络的常见面试问题
  15. 苹果iPhone手机内文件目录大全
  16. 网络安全 -- 暴力破解
  17. 寄东西怕快递丢件?往里扔个AirTag能追踪吗?
  18. 和与余数的和同余理解_余数与同余问题
  19. 凹凸曼但没有小怪兽 CSS的世界
  20. 网络音乐api接口,歌词api接口,免费

热门文章

  1. deepin安装mysql记录
  2. Spark在Ubuntu中搭建开发环境
  3. 【转】Freeglut 2.6.0 + VS2008下配置方法
  4. 二进制文件转成文本保存,并可以读回
  5. 19/03/17Python笔记
  6. 如何创建 Visual Studio 2017 RC 离线安装包
  7. html5 webStorage:localStorage sessionStorage
  8. CSS3实现轮播图效果
  9. 处理11gR2 RAC集群资源状态异常INTERMEDIATE,CHECK TIMED OUT
  10. python工具包: argparse