美文网首页
第五章 标准IO

第五章 标准IO

作者: laidian | 来源:发表于2018-04-24 00:34 被阅读18次

    标准IO不仅仅是unix实现了。

    这个库是ISO C标准说明。

    Single UNIX Specification对ISO C进行了补充,定义了另外一些接口。

    流和FILE对象

    第三章围绕fd,而这章函数围绕流

    流的定向决定了读写字符是单字节还是多字节-宽

    在未定义的流上使用单字节IO函数或者多字节IO函数,则流的定向将被设置单或者宽

    只有两个函数可以改变流的定向:freopen和fwide

    #include <stdio.h>
    #include <wchar.h>
    int fwide(FILE *fp,int mode);//流宽定向返回正值,字节定向返回负值,为定向返回0
    设定流的定向,前提条件是未被设定流的定向
    流可能无效,那么需要前后检查errno
    
    macos的FILE定义
    typedef struct __sFILE {
        unsigned char *_p;  /* current position in (some) buffer */
        int _r;     /* read space left for getc() */
        int _w;     /* write space left for putc() */
        short   _flags;     /* flags, below; this FILE is free if 0 */
        short   _file;      /* fileno, if Unix descriptor, else -1 */
        struct  __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
        int _lbfsize;   /* 0 or -_bf._size, for inline putc */
    
        /* operations */
        void    *_cookie;   /* cookie passed to io functions */
        int (* _Nullable _close)(void *);
        int (* _Nullable _read) (void *, char *, int);
        fpos_t  (* _Nullable _seek) (void *, fpos_t, int);
        int (* _Nullable _write)(void *, const char *, int);
    
        /* separate buffer for long sequences of ungetc() */
        struct  __sbuf _ub; /* ungetc buffer */
        struct __sFILEX *_extra; /* additions to FILE to not break ABI */
        int _ur;        /* saved _r when _r is counting ungetc data */
    
        /* tricks to meet minimum requirements even when malloc() fails */
        unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */
        unsigned char _nbuf[1]; /* guarantee a getc() buffer */
    
        /* separate buffer for fgetln() when line crosses buffer boundary */
        struct  __sbuf _lb; /* buffer for fgetln() */
    
        /* Unix stdio files get aligned to block boundaries on fseek() */
        int _blksize;   /* stat.st_blksize (may be != _bf._size) */
        fpos_t  _offset;    /* current lseek offset (see WARNING) */
    } FILE
    
    
    /* stdio buffers */
    struct __sbuf {
        unsigned char   *_base;
        int     _size;
    };
    

    缓冲

    全缓冲

    满了才flush

    行缓冲

    遇到换行符就flush,终端是行缓冲

    不带缓冲

    一般标准错误就是不带缓冲的

    更改系统缓冲类型

    #include <stdio.h>
    void setbuf(FILE *restrict fp,char *restrict buf);//通常全缓冲
    int setvbuf(FILE *restrict fp,char *restrict buf,int mode,size_t size);
    setvbuf(fp,buf,_IOFBF,BUFSIZE) 相当于 setbuf(fp,buf)
    /*
    mode:
    _IOFBF
    _IOLBF
    _IONBF
    */
    使该流所有未写的数据都被传送至内核
    int fflush(FILE *fp);//出错返回EOF
    

    打开流

    #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 stream);
    FILE *fdopen(int fd,const char *type);
    type:15种不同的值
    /*
    
    */
    int fclose(FILE *fp);
    

    fopen:文件名打开

    freopen:指定一个流上打开文件

    fdopen:fd打开,一般用于管道和网络通信

    ps:ISO C并不涉及文件描述符fd,而POSIX.1具有

    读和写流

    打开流有三种不同类型的非格式化IO

    1. 每次一个字符的IO
    2. 每次一行的IO,可用fgets和fputs
    3. 直接IO(别称:二进制IO),可用fread和fwrite
    #include <stdio.h>
    输入函数
    int getc(FILE *fp);
    int fgetc(FILE *fp);
    int getchar(void);
    /*
    getchar等同于getc(stdin)
    getc和fgetc:
    */
    输出函数
    int putc(int c,FILE *fp);
    int fputc(int c,FILE *fp);
    int putchar(int c);   
    

    3个函数出错和到达文件尾端都是返回相同值,需要下面两个函数做区分

    大多数每个流在FILE对象中维护两个标志

    出错标志

    文件结束标志

    #include <stdio.h>
    int ferror(FILE *fp);
    int feof(FILE *fp);
    
    void clearerr(FILE *fp);
    
    int ungets(int c,FILE *fp);//实质也是写到缓冲区
    

    clearerr可以清除上面两个标志

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

    行IO

    #include <stdio.h>
    char *fgets(char *restrict buf,int n,FILE *restrict fp);//从指定流读到缓冲区
    char *gets(char *buf);//从标准输入读,不推荐用了
    
    int fput(const char *restrict str,FILE *restrict fp);//写到指定流
    int puts(const char *str);//还是不用用
    

    二进制IO

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

    定位流

    ftell,fseek 文件位置放在一个长整型中

    ftello,fseeko 使用off_t

    fgetpos,fsetpos 使用抽象数据类型fpos_t,非UNIX系统可以使用

    #include <stdio.h>
    long ftell(FILE *fp);//success:当前文件位置指示 fail:-1L
    int fseek(FILE *fp,long offset,int whence);
    void rewind(FILE *fp);//将流设置到文件其实位置
    
    off_t ftello(FILE *fp);//与ftell大致相同
    int fseeko(FILE *fp,off_t offset,int whence);//与fseek相同
    
    int fgetpos(FILE *restrict fp,fpos_t *restrict pos);
    int fsetpos(FILE *fp,const fpos_t *pos);
    
    

    格式化IO

    #include <stdio.h>
    int printf
    int fprintf
    int dprintf
    int sprintf
    int snprintf
    
    #include <stdio.h>
    #include <stdarg.h>
    printf变体
    int vprintf
    int vfprintf
    int vdprintf
    int vsprintf
    int vsnprintf
    
    #include <stdio.h>
    int scanf
    int fscanf
    int sscanf
    
    #include <stdio.h>
    #include <stdarg.h>
    int vscanf
    int vfscanf
    int vsscanf
    
    

    实现

    #include <stdio.h>
    int fileno(FILE *fp);//对一个流使用,获取这个流的fd
    

    标准IO库最终都要调用第三章的IO历程

    临时文件

    #inlucde <stdio.h>
    char *tmpnam(char *ptr);//产生一个有效路径名字符串
    FILE *tmpfile(void);//先产生一个唯一路径名,然后,用此创建一个文件,并立即unlink
    
    #include <stdlib.h>
    char *mkdtemp(char *template);//创建目录 
    
    int mkstemp(char *template);//创建名字 返回fd
    

    应该使用tmpfile和mkstemp

    内存流

    #include <stdio.h>
    FILE *fmemopen(void *restrict buf,size_t size,const char *restrict type);
    #include <stdio.h>
    FILE *open_memstream(char **bufp,size_t *sizep);
    #include <wchar.h>
    FILE *open_wmemstream(wchar_t **bufp,size_t *sizep);
    

    标准IO的替代软件

    快速IO库fio

    sfio

    mmap

    习题

    标准IO流怎么使用fsync

    先调用fflush( 全都送到内核),再调用fsync(内核写到缓冲区,然后才能写入磁盘,fd可以通过fileno获取)

    fgets通常处理行缓冲,自动冲洗的

    相关文章

      网友评论

          本文标题:第五章 标准IO

          本文链接:https://www.haomeiwen.com/subject/itqdlftx.html