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\n");
  8. /*this output will go to a file test.out*/
  9. printf("Hello World\n");
  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\n", "Hello world!");
  7. fp =fdopen(1,"w+");
  8. fprintf(fp,"%s\n","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那么不安全,但是一般也不使用,因为它会在字节流后加入换行符,给我们一些情况造成困扰。




APUE学习笔记——5.5~5.7数据流的打开与读写的更多相关文章

  1. APUE学习笔记——10.9 信号发送函数kill、 raise、alarm、pause

    转载注明出处:Windeal学习笔记 kil和raise kill()用来向进程或进程组发送信号 raise()用来向自身进程发送信号. #include <signal.h> int k ...

  2. APUE学习笔记3_文件IO

    APUE学习笔记3_文件IO Unix中的文件IO函数主要包括以下几个:open().read().write().lseek().close()等.这类I/O函数也被称为不带缓冲的I/O,标准I/O ...

  3. apue学习笔记(第一章UNIX基础知识)

    总所周知,UNIX环境高级编程是一本很经典的书,之前我粗略的看了一遍,感觉理解得不够深入. 听说写博客可以提高自己的水平,因此趁着这个机会我想把它重新看一遍,并把每一章的笔记写在博客里面. 我学习的时 ...

  4. APUE学习笔记-一些准备

    从开始看APUE已经有快一个星期了,由于正好赶上这几天清明节放假,难得有了三天空闲假期可以不受打扰的学习APUE,现在已经看完前六章了,里面的大部分例程也都亲自编写,调试过了.但总觉得这样学过就忘,因 ...

  5. APUE学习笔记(2):lseek()练习与文件洞

    对于lseek函数早在大一的C语言课上就有接触,但是几乎没有使用过,只记得是和文件偏移操作相关的 看了APUE上的示例,又使用od工具查看了内容,果然很神奇,很新鲜 figure3.2.c [c] # ...

  6. APUE学习笔记(1):APUE运行环境

    APUE全称<Advanced Programming in the UNIX Environment>(UNIX环境高级编程) 书中例子大都使用作者自己写的头文件,所以需要解决一下,还好 ...

  7. apue学习笔记(第十七章 高级进程间通信)

    本章介绍一种高级IPC---UNIX域套接字机制,并说明它的应用方法 UNIX域套接字 UNIX域套接字用于在同一台计算机上运行的进程(无关进程)之间的(全双工)通信.相比于因特网套接字,UNIX域套 ...

  8. apue学习笔记(第十六章 网络IPC:套接字)

    本章将考察不同计算机(通过网络连接)上的进程相互通信的机制:网络进程间通信. 套接字描述符 正如使用文件描述符访问文件,应用程序用套接字描述符访问套接字. 许多处理文件描述符函数(如read和writ ...

  9. kinect学习笔记(四)——各种数据流

    一.kinect开发的一个流程图 1.我们可以知道一个简单的框架就是几部分 (1)选择使用的kinect传感器 KinectSensor.KinectSensors[] (2)打开需要的数据流 _ki ...

随机推荐

  1. Ubuntu16.04安装和卸载MySQL 5.7

    介绍: MySQL 是一种开源数据库管理系统,通常作为流行的LAMP(Linux,Apache,MySQL,PHP / Python / Perl)堆栈的一部分安装.它使用关系数据库和SQL(结构化查 ...

  2. C++ 顺序表实现

    线性表就是字面上的意思, 顺序表是线性表基于数组的一种实现, “顺序”这个名字怎么来的并不清楚,可以勉强解释为“存储地址是连续.顺序的”. 另外两种线性表实现分别是“基于链表”和“散列存储”. 顺序表 ...

  3. JQuery的click、bind、delegate、off、unbind

    .click与.bind .click和.bind都是给每个元素绑定事件,对于只绑定一个click事件,.bind事件的简写就是.click那种方式. 这两种方式都会出现两个问题: 第一个问题,如果要 ...

  4. Zabbix 关联onealert实现电话报警

    Zabbix 关联onealert实现电话报警 系统环境:Linux Centos 7.4 应用版本:Zabbix 3.0.22 OneAlert官方地址:http://www.onealert.co ...

  5. 20145328 《Java程序设计》实验五实验报告

    20145328 <Java程序设计>实验五实验报告 实验名称 Java网络编程 实验内容 用书上的TCP代码,实现服务器与客户端. 客户端与服务器连接 客户端中输入明文,利用DES算法加 ...

  6. KALI视频学习11-15

    KALI视频学习11-15 第十一集 看到openvas的主界面(web界面) ping靶机,看是否能正常连通 创建一个扫描目标Configuration-Targets,默认扫描目标为本机 添加一个 ...

  7. php-fpm 信号

    使用信号之前,需要先确保php-fpm.conf 里面有配置pid,默认是被注释掉的. ;pid = run/php-fpm.pid 文件在 php安装目录/var/run/php-fpm.pid 信 ...

  8. Jquery15 插件

    学习要点: 1.插件概述 2.验证插件 3.自动完成插件 4.自定义插件 插件(Plugin)也成为 jQuery 扩展(Extension),是一种遵循一定规范的应用程序接口编写出来的程序.目前 j ...

  9. #ifndef用法

    用于避免重复包含头文件 #ifndef _STDIO_H_ #define _STDIO_H_ ...... #endif

  10. Docker storage drivers

    因为Docker的镜像是分层的,包含只读层和可读写层,因此选择正确的Storage Driver对于容器的性能是非常重要的. 支持的Linux发行版本 目前推荐使用性能最好的Overlay2.RHEL ...