5、标准I/O库

1、标准IO库(IO指文件的读写)由ISO C说明,不仅UNIX,其他很多操作系统都实现。前面的非缓冲IO,打开一个文件即返回一个文件描述符。标准IO库打开或创建一个文件时,就使一个流和一个文件相关联。

2、流的定向:国际字符集的一个字符可用多个字节表示,流的定向就是决定所读、写的字符是单字节还是多字节。

#include <wchar.h>
//该函数不改变已定向的流
//当还没定向时,mode>0,使流是宽定向;mode<0使单字节定向,mode=0,未定向
//流是宽定向返回正值;单字节返回负值,未定向返回0
//FILE对象包括IO文件描述符,指向该流缓冲区的指针,缓冲区长度......
int fwide(FILE *fp, int mode);

3、标准输入、输出、错误
标准IO流通过文件指针stdin、stdout、stderr加以引用;这些流引用的文件和前面文件描述符STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO所引用的相同

4、缓冲
    标准IO库提供缓冲的目的是减少读写的次数。全缓冲、行缓冲、不带缓冲。一般系统默认:标准输出不带缓冲,直接输出。指向终端的流是行缓冲。其他为全缓冲。
    冲洗flush:(1)把缓冲区的内容写到磁盘;(2)终端驱动程序方面,丢弃缓冲区中的数据。

//打开缓冲机制,buf=NULL关闭
void setbuf(FILE *restrict fp, char *restrict buf);

//mode为_IOFBF、_IOLBF、_IONBF分别制定为全、行、无缓冲
//若buf=NULL,自动指定缓冲区
//成功返回0,出错非0
int setvbuf(FILE *restrict fp, char *restrict buf, int mode, size_t size);

//强制冲洗一个流
int fflush(FILE *fp);

5、打开流

//type 指定打开方式,b代表二进制文件,r、w重建写、a追加、r+、w+、a+不同的可读写方式,UNIX内核对二进制不加区分
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);

//关闭流,一个进程正常终止时,所有未写缓冲数据的标准IO都被冲洗,所有打开的标准IO流都被关闭

6、读写流
    标准IO库没有read、write函数只有getput(有fwrite和fread用于读写多个结构体)

//读一个字符
int getc(FILE *fp);//实现为宏
int fgetc(FILE *fp);//实现为函数
int getchar(void);//等于getc(stdin)

//输出一个字符
int putc(int c, FILE *fp);//实现为宏
int fputc(int c, FILE *fp);//实现为函数
int putchar(int c); //等于putc(c,stdout)

//出错和到达底部EOF都返回-1,下面函数用以区分
int ferror(FILE *fp);
int feof(FILE *fp);
void clearerr(FILE *fp);//清除这两个标志

//把字符再压回流中(缓冲区中)
int ungetc(int c, FILE *fp);
//每次一行,不建议使用gets(),不指定缓冲区长度可能造成缓冲区溢出
//缓冲区总是以null字符结尾,gets不将换行符存入缓冲区
char *fgets(char *restrict buf, int n, FILE *restrict fp);
char *gets(char *buf);//从标准输入读入

//fputs不一定每次输出一行,因为字符串不一定在null之前存换行符,虽然通常是这样。
int fputs(const char *reatrict str, FILE *restrict fp);
int puts(const char *st);

7、二进制I/O
    一次读或写一个完整的结构,只能读同一个系统上已写的数据。

//从文件fp中读nobj个对象,每个对象长度是size,到地址ptr
//返回读写对象的长度
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);

7、定位流

//从文件起始位置开始
int ftell(FILE *fp);

int fseek(FILE *fp, long offset, int whence);

//将一个流设置到起始位置
void rewind(FILE *fp);

//ISO C引入下面函数
//获取当前文件fd的位置到*posint fgetpos(FILE *restrict fp, fpos_t *restrict pos);
//*pos设为位置
int fsetpos(FILE *fp, const fpos_t *pos);

8、格式化IO,printf输出到终端,fprintf输出到文件名指定的文件,dprintf输出到文件描述符指定的文件,sprintf输出到指定缓冲区buf中,vprintf参数列表为字符串数组

(1)格式化输出,控制参数如何编写,如何显示

//到标准输出
int printf(const char *restrict 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 format, ....);


//5种变种,... 变为 arg
int vprintf(const char *restrict format, va_list arg);

//输出到文件
int vfprintf(FILE *restrict fp, const char *restrict format, va_list arg);

int vdprintf(int fd, const char *restrict format, va_list arg);

//输出到指定缓冲区
int vsprintf(char *restrict buf, const char *restrict format, va_list arg);

int vsnprintf(char *restrict buf, size_t n, const char *restrict format, va_list arg);

(2)格式化输入

//从终端输入到缓冲区
int scanf(const char *restrict format, ...);
//从文件输入到缓冲区  
int fscanf(FILE *restrict fp, const char *restrict format, ...);
int sscanf(const char *restrict buf, const char *restrict format, ...);

int vscanf(const char *restrict format, va_list arg);
//从文件输入到缓冲区  
int vfscanf(FILE *restrict fp, const char *restrict format, va_list arg);
int vsscanf(const char *restrict buf, const char *restrict format, va_list arg);

9、创建临时文件

//ptr存生成的路径名,若为NULL则生成路径名存放在一个静态区中,再次调用会覆盖
char *temnam(char *ptr);
//创建二进制文件,关闭文件或程序结束时自动删除
FILE *temfile(void);

//XSI扩展
//创建目录,tempalte后6个字符应为XXXXXX,如tempalte[]=123XXXXXX,调用该函数会生成路径,文件名的后6位会改变
char *mkdtemp(char *tempalte);
//创建成功返回文件描述符
int mkstemp(char *template);

//使用数组,名字在栈上分配
char good_template[]="/tmp/dirXXXXXX";
//使用指针,只有指针自身驻留在栈上,编译器把字符串存放在可执行文件的只读段,不可改
char *bad_template[]="/tem/dirXXXXXX";
#include "apue.h"
int main(void)
{
    char name[L_tmpnam], line[MAXLINE];
    FILE *fp;
    printf("%s\n", tmpnam(NULL));
    tmpnam(name);
    printf("%s\n", name);

    if((fp = tmpfile()) == NULL)
        err_sys("tmpfile error");
    fputs("one line of output\n", fp);
    rewind(fp);
    if(fgets(line, sizeof(line), fp)==NULL)
        err_sys("fgets error");
    fputs(line, stdout);
    exit(0);
}

10、内存流

//标准IO库把数据缓存在内存中
//非追加方式,当前位置是缓冲区的开始位置
//以追加方式打开内存流,当前文件位置设为缓冲区的第一个null字节,如果缓冲区不存在null字节,则当前位置就设为缓冲区结尾的后一个字节
//任何时候增加缓冲区中数据,及调用fclose、fflush、fseek、fseeko、fsetpos,都会在当前位置写入一个null字节
FILE *fmemopen(void *restrict buf, size_t size, const char *restrict type);

    标准IO库使用每次一行函数fgets和fputs时,通常需要复制两次:一次在内核和标准IO缓冲区之间(当调用read和write时);一次在标准缓冲区IO和用户行缓冲区之间

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值