zoukankan      html  css  js  c++  java
  • APUE学习笔记——5.5~5.7数据流的打开与读写

    1.open

    1. #include <stdio.h>
    2. FILE *fopen(const char *restrict pathname,const char *restrict type)
    3. FILE *freopen(const char *restrict pathname,const char *restrict type,FILE *restrict fp);
    4. FILE *fdopen(int fd,const char *type);
    5. --All three return: file pointer if OK,NULLon error
        fopen:用于打开一个特定的文件
        freopen:在特定的流上打开特定的文件,主要用于实现重定向功能。如果流已经被打开,则先关闭它,如果流已经被含有定向设置,则清除它,重新进行设置。经常用在标准输入流、标准输出流、标准错误流的操作。(eg:标准输出重定向到一个文件)
        fdopen:使打开的文件描述符与标准I/O流向结合。这里的文件描述符可能来自open、dup、dup2、pipe、fcntl等。很多文件只能由网络通信或者创建管道获得的文件描述符,无法直接使用fopen函数。这些特殊的文件打开后就需要与标准I/O流向结合,因此需要fdopen函数。
        关于type的取值如Figure5.2所示

    example:

    关于freopen
    1. #include<stdio.h>
    2. int
    3. main()
    4. {
    5. /*redirect standard output to file test.out*/
    6. if(freopen("./test.out","w",stdout)==NULL)
    7. fprintf(stderr,"errorredirectingstdout ");
    8. /*this output will go to a file test.out*/
    9. printf("Hello World ");
    10. /*close the standard output stream*/
    11. fclose(stdout);
    12. return 0;
    13. }
    printf函数的输出   Hello World会被重定向到test.out中,而不是直接在终端显示。
    关于fdopen
    1. #include<stdio.h>
    2. int
    3. main()
    4. {
    5. FILE *fp = fdopen(0,"w+");
    6. fprintf(fp,"%s ", "Hello world!");
    7. fp =fdopen(1,"w+");
    8. fprintf(fp,"%s ","Hello world!");
    9. fclose(fp);
    10. }
    输出 
            Hello world!
            Hello world!
    首先将标准输入流与标准I/O流的"w+"结合,这样就可以用fprintf对标准输入流写入数据Hello world!
    然后将标准输出流与标准I/O流的"w+"结合,这样就可以用fprintf对标准输出流写入数据Hello world!(在此之前,标准输入流的数据Hello world会被先刷新输出。)   

    2.read and write

        非格式化的数据读写操作可以分为三种类型(这里的非格式化是针对scanf和printf系这样的格式化读写而言)
        ~一次一个字符
        ~一次一行字符
        ~直接I/O:
    Input function:
    1. #include <stdio.h>
    2. int getc(FILE *fp);
    3. int fgetc(FILE *fp);
    4. int getchar(void);
    5. All three return: next character if OK,EOFon end of file or error
            getchar()相当于fp为标准输入的getc,也就是getc()(stdin)
            getc和fgetc的区别在于fgetc()一定是一个函数,而getc()则一般被实现为一个宏,也就是说getc的定义可能是这样的:
    1. #define getc(_fp) _IO_getc (_fp)
            因为getc是一个宏,那么我们就不能使用带副作用的表达式作为它的参数,比如++i。设想如果我们使用++i作为参数,结果将如何。编译器会把函数中所有的_fp替换成++i,这样++i在函数中就可能被调用多次,也就是发生了多次的自加,结果显然不是我们需要的。
            宏的优点在于效率,函数调用需要花费时间。

        这三个函数在返回下一个字符时,都会将它从unsigned char 转化为 int。之所以制定为unsigned 是为了防止在高位为1时变成负数。

    输入判断
    1. #include <stdio.h>
    2. int ferror(FILE *fp);
    3. int feof(FILE *fp);
    4. Both return: nonzero(true) if condition is true, 0 (false) otherwise
    5. void clearerr(FILE *fp);
            一般来说,每个流都包含两个标志:
            •Anerror flag
            •Anend-of-file flag
            调用clearerr可以将他们清除
    1. #include <stdio.h>
    2. int ungetc(intc,FILE *fp);
    3. Returns:cif OK,EOFon error
            从流中读取数据后,ungetc可以将char再push back回去
            ungetc将一个字节退回输入流,如果该字节没有被读出来,则不能再将其它字节pushback到输入流中。

    Output function
        
    1. #include <stdio.h>
    2. int putc(intc,FILE *fp);
    3. int fputc(intc,FILE *fp);
    4. int putchar(intc);
    5. All three return:cif OK,EOFon error
    关键点与Input function类似。

    行缓冲 Line-at-a-Time I/O

    Input
    1. #include <stdio.h>
    2. char *fgets(char *restrict buf,int n,FILE *restrict fp);
    3. char *gets(char *buf);
    4. Both return:buf if OK,NULL on end of file or error
            fgets表示从流fp中读取n字节数据到buf中。buf中的最后一个字符为null。在读数据的时候,换行符也会被读入。因此,fgets读取的数据应该<=n-1.(包括换行符)。     也就是我们如果在输入流中输入Hello然后回车结束,且n不小于7,那么buf中的数据就是
    “Hello”+回车符+空字符。
            gets()不应该被使用。因为他没有指明buf的上限,因此可以无限读取。程序员需要确保buffer足够大,以便执行读操作是不会溢出。如果数据超过buffer的大小,那么就会有数据被覆盖,导致读取的数据出错。因此,gets()函数仅供娱乐。
            当输入的line比n-1大时,那么只有n-1个字符被读取,其它的字符等待其它fgets读:
    example:
    1. #include<stdio.h>
    2. #define BUFFSIZE 4096
    3. int
    4. main()
    5. {
    6. char buf[BUFFSIZE];
    7. fgets(buf,5,stdin);
    8. puts(buf);
    9. fgets(buf,10,stdin);
    10. puts(buf);
    11. return 0;
    12. }
    13. ~
    运行结果:

    windeal@ubuntu:~/Windeal/apue$ ./exe 
    Hello world!
    Hell
    o world!

    Output
    1. #include <stdio.h>
    2. int fputs(const char *restrict str,FILE *restrict fp);
    3. int puts(const char *str);
    4. Both return: non-negative value if OK,EOFon error
       fputs就是输出str中的字符。
        puts()虽然不会像gets那么不安全,但是一般也不使用,因为它会在字节流后加入换行符,给我们一些情况造成困扰。


  • 相关阅读:
    fetch API 和 ajax
    java 通过数据库名获得 该数据所有的表名以及字段名、字段类型
    自定义注解,通过反射获得注解中的值(详细自定义注解解释)
    main方法中sleep
    eclipse中设置JVM内存
    命令java 找不到或无法加载主类
    windows下的命令
    mac terminal基本命令
    ThreadLocal 源码剖析
    SQL中的函数用法
  • 原文地址:https://www.cnblogs.com/Windeal/p/4284659.html
Copyright © 2011-2022 走看看