zoukankan      html  css  js  c++  java
  • [APUE]标准I/O库

      一、流和FILE对象

      标准I/O库对应文件的操作是围绕流(stream)进行的。当用标准I/O库打开或创建文件时,便使一个流与一个文件相关联。标准I/O库的函数对于文件的描述是基于FILE对象指针的,该对象是一个结构体,包含了I/O库管理流所需要的全部信息:用于实际I/O的文件描述符、指向流缓存的指针、缓存长度、当前在缓存中的字符数、出错标志等。

      在标准I/O中,一个打开的文件称为流(stream),流可以用于读(输入流)、写(输出流)或者是读写(输入输出流)。每个进程在启动后就会打开三个流,与打开的三个文件相对应:stdin代表标准输入流,stdout代表标准输出流,stderr代表标准错误输出流,它们都是(FILE*)型的指针。

      二、缓存

      有缓存就会有延迟,即输出设备上的内容和缓存中的内容很可能不一样。可以调用fflush刷新缓存。
      有多种缓存类型,可以调用下面的API来更改默认缓存类型:setbuf,  setvbuf。
      setvbuf可以精确的说明缓存的类型;fclose关闭流时也会刷新流。
      当一个进程正常终止时(直接调用exit或从main函数返回),则所有带未写缓存数据的标准I/O流都会被刷新,所有打开的标准I/O流都会被关闭。

      三、与Unix I/O的区别

      UNIX I/O的函数都是针对文件描述符的,而标准I/O的操作都是围绕流进行的,所为的流就是一个FILE *。
      标准I/O提供了缓存--为了尽量减少write, read的调用。
      标准I/O的效率会低一些,因为它是多了一层封装。即,fread通过调用read来实现。
     
    四、API
    打开流
    fopen函数用于打开一个文件流,其原型如下:  FILE *fopen(const char *filename, const char *mode);

    filename:被打开的文件的名称(可包含路径)。  

    mode:字符串,用于表示打开的模式。  

    返回值:打开成功后的文件指针,失败则返回NULL。

    mode如下:

    字符串                     含义

    r 或 rb                    以只读方式打开

    w 或 wb           以只写方式打开,若文件有内容,则清空  

    a 或 ab            以只写方式打开,原内容保留,写入的内容附加在文件流尾部

    r+ 或 rb+ 或 r+b     以更新方式打开,此时文件可读可写  

    w+ 或 wb+ 或 w+b    以更新方式打开,文件可读可写,但打开时清空文件内容  

    a+ 或 ab+ 或 a+b      以更新方式打开,文件可读可写,写入的内容附加在文件流尾部

    读写流
    每次一个字符的I/O
    getc, fgetc, getchar
    getc一般是宏调用,效率高于fgetc。fgetc可以作为一个地址传递给其它函数。
    int getc(FILE * stream);
    int fgetc(FILE *stream);
    int getchar(void) 相当于 getc(stdin);
    从一个流读取一个字符后,可以调用ungetc将字符再送回流中。
    上面三个API出错或到达文件尾都返回-1。具体是什么情况,需要调用下面的两个API来判断:
    int ferror(FILE *stream);
    int feof(FILE *stream);
    什么情况下会用到回送字符呢?
    当正在读一个输入流,并进行某种形式的分字或分记号操作时,会经常用到回送字符操作。
    有时需要先看一看下一个字符,以决定如何处理当前字符。然后就需要方便地将刚查看的字符
    送回,以便下一次调用g e t c时返回该字符。
    对应的输出:
    putc, fputc, putchar
     
    每次一行的I/O
    gets, fgets
    char * fgets(char * s,int size,FILE * stream);
    char *gets(char *s);
    fgets从文件读入, gets从表中输入读入。
    fgets()用来从参数 stream所指的文件内读入字符并存到参s所指的内存空间,直到出现换行字符、读到文件尾或是已读了 size-1个字符为止,最后会加上 NULL作为字符串结束。换行符也包含在字符串中。去除换行符:s[strlen(s)-1]=0;
    gets会自动删除新行符。建议不要使用gets,因为容易造成缓冲区溢出。
    对应的输出:
    fputs 之后不会输出一个新行符
    puts 之后会输出一个新行符
     
    指定长度的I/O
    上面的API主要用来处理文本文件,对于结构类型的内容或结构中含有null字符或换行符的情况,不好处理。这就用到下面两个API。
    size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream);
    size_t fwrite(const void * ptr,size_t size,size_t nmemb,FILE * stream);
    两个函数都返回实际读写的对象数。
     
    定位流
    long ftell(FILE * stream);
    int fseek(FILE * stream,long offset,int whence);
    void rewind(FILE * stream);  相当于fseek(stream, 0, SEEK_SET);
    下面两个的可移植性会好些
    int  fgetpos(FILE *, fpos_t *);
    int fsetpos(FILE *, const fpos_t *);
     
    格式化I/O
    printf将格式化数据写到标准输出,fprintf写至指定的流,sprintf将格式化的字符送入数组buf中。
    sprintf在该数组的尾端自动加一个null字节,但该字节不包括在返回值中。
    int fprintf(FILE * stream, const char * format,.......);
    int sprintf( char *str,const char * format,.........);
    int printf(const char * format,.......);
     
    对应的三个格式化输入
    int fscanf(FILE * stream, const char * format,.......);
    int sscanf( char *str,const char * format,.........);
    int scanf(const char * format,.......);
    标准I/O的实现细节
    在UNIX上,标准I/O是调用UNIX的I/O来实现的,类似
    fread()
    {
      ……
      read()
      ……
    }
    每个流都有对应的文件描述符
    可以调用int fileno(FILE *fp)来获得,如果要调用dup或fcntl等函数,需要用到这个转换。
     
    创建临时文件
    FILE *tmpfile(void) -- linux下可用
    char *tmpnam(const char *)  -- linux下不可用
    char *tempnam(const char *dir, const char *prefix); -- linux下不可用
     
    char * mktemp(char * template); -- linux下可用
    参数 template所指的文件名称字符串中最后六个字符必须是 XXXXXX。
    linux下的一个例子:
    char template[ ]="aaaaa-XXXXXX"; 
    mktemp(template);
    或 mkdtemp(template);
     
    引用文献:
    1、http://www.cnblogs.com/wblyuyang/archive/2012/11/07/2759423.html
    2、http://www.cnblogs.com/uvsjoh/archive/2012/06/13/2547743.html
    3、http://blog.csdn.net/kangroger/article/details/38708297
  • 相关阅读:
    PorterDuff及Xfermode初识
    Android内存优化之——static使用篇
    Realm for Android快速入门教程
    Android 你应该知道的学习资源 进阶之路贵在坚持
    Google 发布 Android 性能优化典范
    Android Studio 打包及引用 aar
    Android CoordinatorLayout + AppBarLayout(向上滚动隐藏指定的View)
    elevation 和 translationZ的区别
    rsync+inotify实时数据同步多目录实战
    rsync+inotify实时数据同步单目录实战
  • 原文地址:https://www.cnblogs.com/kona/p/4648362.html
Copyright © 2011-2022 走看看