zoukankan      html  css  js  c++  java
  • 标准IO

    标准IO由ISO C 标准的IO库,它处理了很多底层细节,比如合适的缓冲大小等等,因此更易于使用,但是也引入了一些其他问题。

    流向

    标准IO使用FILE对象关联流,流可以是面向宽字节的也可以是面向单字节的,当流初始化的时候是没有方向的,如果后面的IO操作是处理的宽字符集的,流变成面向宽字节的,如果哦是处理单字节的,流变成面向单字节,一旦流有了方向,不可改变,直到流被关闭,fwide可以设置流的方向,freopen可以清楚流的方向。

    #include <wchar.h>
     int fwide(FILE *stream, int mode);

    如果mode值大于0,函数尝试设置流面向宽字节,如果mode值小于0,函数尝试流面向单字节,mode值等于0,函数返回当前流的方向。

    如果流已经有了方向,fwide不会设置流的方向。返回没有出错返回,唯一的方法是在函数调用之前清除errno,在调用函数后检查errno。

    在标准IO中,stdin,stdout,stderr 预定义指针对应STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO.

    缓冲

    标准IO操作时提供了合适的缓冲大小,不需要我们自己指定,同时提供了三种类型的缓冲:

    1.全缓冲:只有当缓冲区满了之后才会进行IO操作

    2.行缓冲 :遇到换行符或者缓冲区满了之后进行IO操作

    3 无缓冲 :立即执行

    一般来说面向交互式终端的是行缓冲,错误输出是无缓冲,其他情况是全缓冲的。通过setbuf和setvbuf可以改变默认行为:

    #include <stdio.h>
    void setbuf(FILE *restrict fp, char *restrict buf );
    int setvbuf(FILE *restrict fp, char *restrict buf, int mode, size_t size);
        //Returns: 0 if OK, nonzero on error

    setbuf函数如果buf设置为NULL,则是无缓冲,如果非NULL,必须是指向BUFSIZ长度的缓冲区地址,此时是全缓冲的。

    setvbuf函数允许通过mode控制缓冲行为:

    _IOFBF fully buffered

    _IOLBF line  buffered

    _IONBF no   buffered

    buf一般使用NULL,这时size没有意义,这让标准库去关联缓冲,省去了不少麻烦。

    注意:上面的函数必须在流打开后以及任何IO操作之前调用。

    任何时候都可以通过fflush冲洗流:

    #include <stdio.h>
    int fflush(FILE *fp);
    //Returns: 0 if OK, EOF on error

    如果fp为NULL,函数冲洗所有输出流。

    打开流:

    #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 fp);//在指定的FILE对象上打开流,如果流已经存在先关闭它,如果流有方向先清除方向
    FILE *fdopen(int fd, const char *type);//将fd打开为标准流
    //All three return: file pointer if OK, NULL on error

    type取值如下:

    r or rb  打开为只读

    w or wb 创建为写或者清空

    a or ab 追加或者创建为写或者打开为在尾端写

    r+ or r+b or rb+ 读写

    w+ or w+b or wb+ 清空或者创建为读写

    a+ or a+b or ab+ 打开或者创建为尾端读写

    当文件打开为读写的时候,有下面的限制:

    写之后没有执行fflush,fseek,rwind,fsetpos不可以读

    读之后没有执行fseek,fsetpos ,rewind不可以写。

    关闭流:

    #include <stdio.h>
    int fclose(FILE *fp);
    //Returns: 0 if OK, EOF on error

    所有缓冲的输出数据都会在文件关闭之前冲洗,输入数据可能被丢弃。在进程正常关闭的时候,所有未写的缓冲数据都会被冲洗,并且流都会被关闭。

    流读写:

    1.一次一字符:

    #include <stdio.h>
    int getc(FILE *fp);
    int fgetc(FILE *fp);
    int getchar(void);
    int putc(int c, FILE *fp);
    int fputc(int c, FILE *fp);
    int putchar(int c);
    //All three return: next character if OK, EOF on end of file or error

    注意getc,fgetc getchar都是返回的字符是unsigned char强制转换为int,千万不要赋值给char变量。

    2.一次一行:

    #include <stdio.h>
    char *fgets(char *restrict buf, int n, FILE *restrict fp);
    char *gets(char *buf );//容易缓冲溢出,永远不要使用
    //Both return: buf if OK, NULL on end of file or error
    int fputs(const char *restrict str, FILE *restrict fp);
    int puts(const char *str);
    //Both return: non-negative value if OK, EOF on error

    fputs向fp写入str,\0不会写入.

    puts向标准输出写str,\0不会写入但是会换行。

    3.二进制流:

    #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);
    //Both return: number of objects read or written

    如果fread返回值小于nobj说明出错或者达到文件尾,这时必须调用feof或者ferror判断。如果fwrite的返回值小于nobj说明出错。

    流定向:

    #include <stdio.h>
    
           int fseek(FILE *stream, long offset, int whence);
    
           long ftell(FILE *stream);
    
           void rewind(FILE *stream);
    
           int fgetpos(FILE *stream, fpos_t *pos);
           int fsetpos(FILE *stream, fpos_t *pos);

    fseek设置流的pos,where:取值为SEEK_SET 表示文件头,SEEK_CUR当前位置,SEEK_END 文件尾。

    ftell返回流的当前pos。

    rewind将pos指向文件头相当于fseek(stream,0L,SEEK_SET)

    fgetpos和fsetpos同ftell和fseek。

    流格式化:

    输出:

    #include <stdio.h>
    int printf(const char *restrict format, ...);
    int fprintf(FILE *restrict fp, const char *restrict format, ...);
    int dprintf(int fd, const char *restrict format, ...);
    //All three return: number of characters output if OK, negative value if output error
    int sprintf(char *restrict buf, const char *restrict format, ...);
    //Returns: number of characters stored in array if OK, negative value if encoding error,最好不要用,用下面的
    int snprintf(char *restrict buf, size_t n,const char *restrict format, ...);
    //Returns: number of characters that would have been stored in array if buffer was large enough, negative value if encoding error

    输入:

    #include <stdio.h>
    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, ...);
    //All three return: number of input items assigned,EOF if input error or end of file before any conversion

    说说format格式的转换类型,注意输入的有符号可能会转为无符号的。比如-1可能会扫描为4294967295存储在无符号数中。

    转换类型                                       含义

    c                                                 字符

    s                                                 字符串

    [                                                  列出的字符串,以]结尾

    [^                                                非列出的字符串 ,以]结尾

    stream对象转为FD:

    int fileno(FILE *stream);//函数不会失败

    临时文件:

    #include <stdio.h>
    char *tmpnam(char *ptr);
    //Returns: pointer to unique pathname
    FILE *tmpfile(void);
    //Returns: file pointer if OK, NULL on error

    tmpnam使用ptr产生临时文件,如果ptr为NULL,库会使用静态数组存储名字,多次调用静态数组将被覆盖。成功返回唯一的路径,失败返回空。当参数为NULL时该函数不是线程安全的,应该使用tmpnam_r替代。

    tmpfile产生一个二进制临时文件,流关闭或者进程结束后,文件自动删除。

    UNIX还提供了下面函数生成临时文件:

    #include <stdlib.h>
    char *mkdtemp(char *template);
    //Returns: pointer to directory name if OK, NULL on error
    int mkstemp(char *template);
    //Returns: file descriptor if OK, −1 on error

    mkdtemp相当于mkdir(template,S_IRUSR|S_IWUSR|S_IXUSR)

    mkstemp相当于create(template,S_IRUSR|S_IWUSR)

    注意:使用这两个函数创建的临时文件不会自动删除,需要我们自己删除。由于tmpnam和tempnam不是原子操作,应该使用tmpfile和mkstemp。

  • 相关阅读:
    教你如何用Meterpreter渗透Win系统
    Maven 自动打包上传到私服 Nexus
    从同事的一个提问想到的学习途径
    SAS学习笔记之《SAS编程与数据挖掘商业案例》(1)系统简介和编程基础
    StackOverflowError&OutOfMemoryError区别
    优先使用TimeUnit类中的sleep()
    Java 开源博客 Solo 1.3.0 发布
    Java 开源博客 Solo 1.3.0 发布
    Cleanup failed to process the following paths错误的解决
    Java&Xml教程(六)使用JDOM解析XML文件
  • 原文地址:https://www.cnblogs.com/xiaofeifei/p/4077402.html
Copyright © 2011-2022 走看看