Unix编程笔记(二)标准I/O库

标准I/O库由ISO C标准说明,很多操作系统都实现了标准I/O库。
标准I/O库处理很多细节,如缓冲区分配、以优化的块长度执行I/O等。这些处理使用户不必担心如何选择使用正确的块长度。

与文件I/O的区别:

文件I/O标准I/O
标准输入STDIN_FILENOstdin
标准输STDOUT_FILENOstdout
标准错误STDERR_FILENOstderr
打开文件openfopen\freopen\fdopen 打开方式(b byte以二进制打开,含 + 读写,含 r 不创建,含 w 截断,含 a 追加)
创建文件creat\open(…,O_CREATE…)fopen
关闭文件closefclose
只读O_WRONLYw\wb
只写O_RDONLYr\rb
读写O_RDWRr+ r+b rb+ w+ w+b wb+
追加O_APPENDa ab a+ a+b ab+
创建O_CREATE不含 r 都是创建
定位lseekftell\fseek\rewind\ftello\fseeko\fgetpos\fsetpos
writefwrite
readfread
/*

流和file对象:
    标准I/O库是围绕流进行的,当用标准I/O库打开或创建一个文件时,我们已使一个流与一个文件相关联
    当打开一个流时,fopen返回一个指向FILE对象的指针
    FILE对象包含了标准I/O库为管理该流所需要的所有信息,包括用于实际I/O的文件描述符、指向用于该流缓冲区的指针、缓冲区的长度、当前缓冲区中的字符数以及出错标志

流定向:
    以单字节、多字节读写文件
    fwide: fwide并不改变已经定向的流

    int fwide(FILE* file,int mode)
        file : 打开的文件流指针
        mode : 0 未定向,>0 宽定向、多自己定向,<0 单字节定向
        返回值:0 未定向,>0 宽定向、多自己定向,<0 单字节定向


标准输入输出、标准错误:
    标准流指针:stdin stdout stderr

缓冲:
    缓冲是为了尽可能减少read和write调用的次数
    标准I/O提供了以下3中类型的缓冲:
        1. 全缓冲,缓冲区填满后才进行实际的I/O操作
        2. 行缓冲,输入和输出遇到换行符时,标准I/O库执行操作
        3. 不带缓冲,不对字符进行缓冲存储
    标准错误流stderr通常是不带缓冲的

    更改缓冲类型,需在流打开,但是为执行任何操作前调用:
    void setbuf (FILE * __stream, char * __buf);
        buf = NULL,关闭缓冲区
        buf 长度为BUFSIZE,全缓冲

    int setvbuf (FILE * __stream, char * __buf,int __modes, size_t __n);
        buf、n : 全缓冲或行缓冲时有效,buf=NULL且带缓冲则缓冲区长度未BUFSIZE
        modes : 
            _IOFBF 全缓冲
            _IOLBF 行缓冲
            _IONBF 不带缓冲

    强制冲洗一个流,将缓冲区数据写入文件:
    int fflush(FILE*fp);
        fp: 文件流,为NULL时将导致所有输出流被冲洗。


打开流:
    FILE *fopen (const char *__filename,const char * __modes);
        filename : 文件名称
        modes : 打开方式(b byte以二进制打开,含 + 读写,含 r 不创建,含 w 截断,含 a 追加)
                r rb 只读
                w wb 只写,将文件截断至0长,写创建
                a ab 写追加,写创建
                r+ r+b rb+ 读写
                w+ w+b wb+ 读写,将文件截断至0长,创建
                a+ a+b ab+ 文件尾端读写打开和创建
        成功返回指针,失败返回NULL

    FILE *freopen (const char *__filename,const char *__modes,FILE *__stream);
    在指定的流上打开一个指定的文件,若流已经打开,则先关闭该流;若流已经定向,则使用freopen清除该定向;一般用于标准输出、标准输入和标准错误流重定向

    FILE *fdopen (int __fd, const char *__modes);
    读取一个已有的文件描述符,并使一个标准的I/O流与该描述符相结合


    关闭流:
    fclose(FILE *fp);

    当程序正常终止时,所有缓冲的标准I/O流都被冲洗,所有打开的标准I/O流都被关闭。


读和写流:

    一次读一个字符:
    int getc(FILE *fp); // 这是个宏
    int fgetc(FILE *fp); // 这是个函数
    int getchar(); // 等价于 getc(stdin)

    以上三个函数返回的是字符的ASCII码值,若获取出错或失败,则需要通过以下两个函数:
    int ferror(FILE *fp);
    int feof(FILE *fp);

    FILE对象中维护了两个标志:
        文件出错标志
        文件结束标志
    调用clearerr可以清除这两个标志

    从流中读取数据后,可以调用ungetc将字符压送回流:
    int ungetc(FILE *fp);
    不能回送EOF,一次成功的ungetc会清除文件的EOF标志

    一次写一个字符:
    int putc(int c,FILE *fp);
    int fputc(int c, FILE *fp);
    int putchar(int c); // 等级于 putc(c,stdout);


    每次读一行:
    char *fgets(char *buf,int n,FILE *fp);  // 最多返回n-1个字符,返回buf以null结尾
    char *gets(char *buf);  // 不安全,避免使用,返回值不含null
    成功都是返回buf指针,否则返回NULL

    每次输出一行:
    int fputs(const char *str,FILE *fp);
    int puts(const char *str);

标准I/O的效率:


二进制I/O:
    size_t fread(void *ptr,size_t size,size_t nobj,FILE *fp);
    size_t fwrite(const void *ptr,size_t size,size_t nobj,FILE *fp);
        ptr: 读取或写入数据的指针
        size: 对象内存的大小
        nobj: 对象个数
        fp: 文件描述符
        返回值:对象个数


定位流:
    long ftell(FILE *fp);   // 成功返回文件offset,失败 -1
    int fseek(FILE *fp,long offset,int whence); // 设置文件offset,whence : SEEK_SET\SEEK_CUR\SEEK_END;成功返回0,失败返回-1
    void rewind(FILE *fp);  // 将流设置到文件的起始位置

    off_t ftello(FILE *fp); // 成功返回文件offset,失败 -1;可用于大文件,off_t = long int
    int fseeko(FILE *fp,off_t offset,int whence);   // 成功返回0,出错返回-1

    int fgetpos(FILE *fp,fpos_t pos);   // 超大文件,获取指定文件的offset
    int fsetpos(FILE *fp,const fpos_t *pos);    // 设置指定文件的offset



格式化I/O:

    int prinf(const char * format,...); // 将格式化数据写到标准输出
    int fprintf(FILE *fp,const char * format,...);  // 将格式化数据写到指定流
    int dprintf(int fd,const char * format,...);    // 将格式化数据写到指定文件描述符
    int sprintf(char * buf,const char * format,...);    // 将格式化数据写到指定字符数组缓冲区
    int snprintf(char * buf,size_t n,const char* format,...);   // 将格式化数据写到指定字符数组缓冲区,显式设置字符数组缓冲区长度

    以下五种将可变列表类型改为va_list:
    int vprinf(const char * format,va_list arg); // 将格式化数据写到标准输出
    int vfprintf(FILE *fp,const char * format,va_list arg);  // 将格式化数据写到指定流
    int vdprintf(int fd,const char * format,va_list arg);    // 将格式化数据写到指定文件描述符
    int vsprintf(char * buf,const char * format,va_list arg);    // 将格式化数据写到指定字符数组缓冲区
    int vsnprintf(char * buf,size_t n,const char* format,va_list arg);   // 将格式化数据写到指定字符数组缓冲区,显式设置字符数组缓冲区长度


格式化输入:
    int scanf(const char *format,...);  // 从标准输入格式化输入
    int fscanf(FILE *fp,const char *format,...);    // 从指定流格式化输入
    int sscanf(const char *buf,const char *format,...); // 从指定字符数组缓冲区格式化输入

    可变长参数列表:
    int vscanf(const char *format,va_list arg);  // 从标准输入格式化输入
    int vfscanf(FILE *fp,const char *format,va_list arg);    // 从指定流格式化输入
    int vsscanf(const char *buf,const char *format,va_list arg); // 从指定字符数组缓冲区格式化输入


实现细节:
    获取流的文件描述符:
    int fileno(FILE *fp);


临时文件:
    char *tmpnam(char *ptr);    // 指向唯一路径名的指针
    FILE *tmpfile(void);        // 成功返回文件指针,失败返回NULL

    char *mkdtemp(char *template);  // 创建有唯一名字的目录
    int mkstemp(char *template);    // 创建有唯一名字的文件

内存流:
    像操作文件一样操作内存

    FILE *fmemopen(void * buf,size_t size,const char *type);    //打开内存,buf指向缓冲区地址,size指缓冲区的大小,type与fopen的modes参数一致

    FILE *open_memstream(char **bufp,size_t *sizep);    // 面向字节,只能写打开
    FILE *open_wmemstream(wchar_t **bufp,size_t *sizep);    // 面向宽字节,只能写打开
*/

#include <stdio.h>
#include <wchar.h>

void main()
{
    // 重定向
    // fwide(stdout, -1);

    // setbuf(stdout,)

    // getc(stdin);

    int c = getchar();  // 获取输入值
    putchar(c);         // 输出值

    ungetc('a', stdin);     // 回退
    int a = getc(stdin);    // 读取
    putc(a, stdout);        // 写入
    ungetc('b', stdin);     //
    int b = fgetc(stdin);
    fputc(b, stdout);
off_t
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值