标准I/O库处理很多细节,使得便于用户使用。

流和 FILE 对象

对于标准I/O库,操作是围绕 流(stream)进行的。当用标准I/O打开或创建一个文件时,我们已使一个流与一个文件相关联。

对于ASCII字符集,一个字符用一个字节表示。对于国际字符集,一个字符可用多个字节表示。流的定向决定所读,写的字符是单字节还是多字节。

一个流在创建的最初,并没有定向,如果对未定向的流使用多字节I/O函数,则将该流定向为款定向的,反之如果使用单字节I/O函数,则将流的定向设为字节定向的。

改变流的定向的函数(只有两个):

freopen : 清楚一个流的定向

fwide        :   设置流的定向

int fwide ( FILE *fp , int mode );

宽定向返回正值,字节定向返回负值,未定向的返回0;

  • 如果mode参数为负 , fwide试图使指定的流是字节定向
  • 如果mode参数为正 , fwide试图使指定的流是宽定向的
  • 如果mode参数为 0  , fwide将不试图设置流的定向,但返回标识该流定向的值。

fwide 并不改变已定向流的定向。

标准输入 , 标准输出 , 标准错误。

文件描述符 分别为 STDIN_FILENO , STDOUT_FILENO , STDERR_FILENO

通过预定文件指针 stdin , stdout , stderr。这三个文件指针分别在头文件<stdio.h>中

缓冲

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

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

全缓冲:在填满标准I/O缓冲区后才进行实际I/O操作。

行缓冲:在输入和输出遇到换行符时,标准I/O库执行I/O操作。

不缓冲:比如strerr,这样使得出错信息可以尽快显示出来。

对任何一个给定的流,可以调用下列两个函数中的一个更改缓冲类型。

void setbuf ( FILE *restrict fp , char *restrict buf ) ;

int setvbuf ( FILE *restrict fp , char *restrict buf , int mode , size_t size );

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

使用 setvbuf , 可以精确的说明所需缓冲类型。 mode 参数:

_IOFBF     全缓冲

_IOLBF     行缓冲

_IONBF    不缓冲

147页有图。

打开流

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

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在一个指定的流上打开一个指定的文件 。
  3. fdopen取一个文件描述符,并使一个标准的I/O流与该描述符结合。

type有15种不同的值 —— 图5.2

读和写流

输入函数:

以下三个函数可以一次读一个字符

int getc ( FILE *fp )

int fgetc (FILE *fp )

int getchar ( void )

getchar 等同于 getc(stdin)。

getc可被实现为宏,fgetc不能实现为宏。

  1. getc的参数不应当是具有副作用的表达式
  2. fgetc一定是一个函数,所以可以得到其地址。
  3. 调用fgetc的时间可能比getc的时间长。

由于不管出错还是达到文件尾端。三个函数都是返回同样的值。为了区分,调用ferror 或 feof

int ferror ( FILE *fp )

int feof ( FILE *fp )

在大多数实现中,为每个流在FILE对象中维护了两个标志:

出错标志

文件结束标志

输出函数:

int putc ( int c , FILE *fp )

int fputc ( int c , FILE *fp )

int putchar ( int c )

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

每次一行 I/O

char *fgets ( char *restrict buf , int n , FILE *restrict fp )

char *gets ( char *buf )

gets从标准输入读, fgets 从指定的流读。

对于 fgets , 必须指定缓冲的长度为 n 。 此函数一直读到下一个换行符为止。

gets是一个不推荐使用的函数,因为不能指定在使用gets时缓冲区的长度。可能造成缓冲区溢出。

gets并不将换行符存入缓冲区

fputs 和 puts 提供每次输出一行的功能

int fputs ( const char *restrict str , FILE *restrict fp )

int puts ( const char *str )

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

函数 puts 将一个以 null 字节终止的字符串写到标准输出,终止符不写出。但随后将一个换行符写到标准输出。

应当尽量使用 fgtes 和 fputs。

标准 I/O 的效率

二进制 I/O

以下两个函数用于执行二进制 I/O 操作

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 );

UNIX环境高级编程 标准IO库的更多相关文章

  1. UNIX环境高级编程---标准I/O库

    前言:我想大家学习C语言接触过的第一个函数应该是printf,但是我们真正理解它了吗?最近看Linux以及网络编程这块,我觉得I/O这块很难理解.以前从来没认识到Unix I/O和C标准库I/O函数压 ...

  2. UNIX环境高级编程——标准I/O库

    对一个进程预定义了三个流,并且这三个流可以自动的被进程使用,它们是:标准输入.标准输出.和标准错误. 标准I/O库提供缓冲的目的是尽可能减少使用read和write的次数. 标准I/O库提供了三种类型 ...

  3. UNIX环境高级编程——标准I/O库缓冲区和内核缓冲区的区别

    1.C标准库的I/O缓冲区         UNIX的传统 是Everything is a file,键盘.显示器.串口.磁盘等设备在/dev 目录下都有一个特殊的设备文件与之对应,这些设备文件也可 ...

  4. UNIX环境高级编程——标准I/O库函数和Unbuffered I/O函数

    以写文件为例,C标准I/O库函数(printf(3) .putchar(3) .fputs(3) )与系统调用write(2) 的关 系如下图所示. 库函数与系统调用的层次关系 open .read ...

  5. UNIX环境高级编程——标准IO-实现查看所有用户

    #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h&g ...

  6. (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  7. (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  8. (十一) 一起学 Unix 环境高级编程 (APUE) 之 高级 IO

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  9. Unix环境高级编程:文件 IO 原子性 与 状态 共享

    参考 UnixUnix环境高级编程 第三章 文件IO 偏移共享 单进程单文件描述符 在只有一个进程时,打开一个文件,对该文件描述符进行写入操作后,后续的写入操作会在原来偏移的基础上进行,这样就可以实现 ...

随机推荐

  1. Docker pull网络错误

    [root@Oracle ~]# docker search centos Error response from daemon: Get https://index.docker.io/v1/sea ...

  2. ng2 quickstart

    1.下载 git clone https://github.com/angular/quickstart.git quickstart-angular 2.安装模块 npm install 3.启动 ...

  3. 【jdk源码分析】java多线程开启的三种方式

    1.继承Thread类,新建一个当前类对象,并且运行其start()方法 package com.xiaostudy.thread; /** * @desc 第一种开启线程的方式 * @author ...

  4. C# 操作FTP

    操作FTP管理类: using System; using System.Collections.Generic; using System.Text; using System.Net; using ...

  5. JavaScript高级程序设计-读书笔记(6)

    第20章 JSON JSON是一个轻量级的数据格式,可以简化表示复杂数据结构的工作量 JSON的语法可以表示一下三种类型的值 l        简单值:使用与JavaScript相同的语法,可以在JS ...

  6. 【转】TCP那些事(上,下)

    TCP是一个巨复杂的协议,因为他要解决很多问题,而这些问题又带出了很多子问题和阴暗面.所以学习TCP本身是个比较痛苦的过程,但对于学习的过程却能让人有很多收获.关于TCP这个协议的细节,我还是推荐你去 ...

  7. exit()子程序终止函数与return()函数的差别

    在main函数中我们通常使用return (0);这样的方式返回一个值. 但这是限定在非void情况下的也就是void main()这样的形式. exit()通常是用在子程序中用来终结程序用的,使用后 ...

  8. Docker 生态

    Docker 和容器技术的发展可谓是日新月异,本文试图以全局的视角来梳理一下 docker 目前的生态圈.既然是概览,所以不会涉及具体的技术细节. Docker 自从发布以来发生了很多的变化,并且有些 ...

  9. Project facet Java 1.8 is not supported by target runtime Apache Tomcat v7.0.

    找到项目下的“.settings”

  10. IOS-CocoaPods进阶篇

    一.Podfile.lock文件 上文讲过,在开始使用CocoaPods,执行完pod install之后,会生成一个Podfile.lock文件.这个文件看起来跟我们关系不大,实际上绝对不应该忽略它 ...