5(标准IO)

1 缓冲

标准I/O库提供缓冲的目的是尽可能地减少使用read和write调用的次数。他也对每个I/O流自动地进行缓冲管理,从而避免了应用程序需要考虑这一点所带来的麻烦。不幸的是,标准I/O库最令人迷惑的也是他的缓冲。 标准I/O提供了三种类型的缓冲: 1、全缓冲。这种情况下,在填满标准I/O缓冲区后才进行实际I/O操作。对于驻留在磁盘上的文件通常是由标准I/O库实施全缓冲。一个流上执行第一次I/O操作时,相关标准I/O函数通常调用malloc获得需使用的缓冲区。 术语冲洗说明I/O缓冲区的写操作。缓冲区可由标准I/O例程自动冲洗,或者可以调用函数fflush冲洗一个流。值得引起注意的是在UNIX环境 中,flush有两种意思。在标准I/O库方面,flush意味着将缓冲区中的内容写到磁盘上。在终端驱动程序方面flush表示丢弃已存储在缓冲区中的数据。 2、行缓冲。在这种情况下,当在输入和输出中遇到换行符时,标准I/O库执行I/O操作。这允许我们一次输出一个字符,但只有在写了一行之后才进行实际I/O操作。当流涉及一个终端时,通常使用行缓冲。 3、不带缓冲。标准I/O库不对字符进行缓冲存储。例如,如果用I/O函数fputs写15个字符到不带缓冲的流中,则该函数很可能用write系统调用函数将这些字符立即写至相关联的打开文件中。 ISO C要求下列缓冲特征:

  • 当且仅当标准输入和标准输出并不涉及交互式设备使,他们才是全缓冲的。
  • 标准出错绝不会是全缓冲的。

但是,这并没有告诉我们如果标准输入和标准输出涉及交互式设备时,他们是不带缓冲的还是行缓冲的;以及标准出错时不带缓冲的还是行缓冲的。很多系统默认使用下列类型的缓冲:

  • 标准出错是不带缓缓冲的。
  • 如若是涉及终端设备的其他流,则他们是行缓冲的;否则是全缓冲的。

可调用下列函数中的一个更改缓冲类型

#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

2 打开流

三个函数可以打开一个标准IO流

#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 *fdopen(int filedes, const char *type);
            All three return: file pointer if OK, NULL on error

三者的区别在于:

  • fopen函数:打开路径名为pathname的一个指定的文件
  • fdopen函数:打开已存在的文件描述符,使标准I/O流与该文件相结合。主要用于fopen不能打开的特殊文件(如管道和网路通信等)。这时必须先调用设备专用函数以获得一个文件描述符,然后在用fdopen使一个标准I/O与该文件描述符相结合。
  • freopen函数:在指定的流上打开一个指定的文件,如若该流已经打开,则先关闭该流。若该流已经定向,则使用freopen清除该定向。简单的说可以利用freopen函数重定向。此函数一般用于将一个指定的文件代开为一个预定义的流:stdout,stdin,stderr。

3 读和写流

一旦打开了流,则有三种不同类型的非格式化IO进行选择,对其进行读写操作 (1)每次一个字符的IO。一次读或者写一个字符,如果流是带缓冲的,则标准IO会处理所有缓冲 (2)每次一行IO。就要使用fgets和fputs,每行都以一个换行符终止。 (3)直接IO。fread和fwrite支持这种类型的IO。

4 一次一个字符的IO

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

对应的输出函数

#include <stdio.h>
int putc(int c, FILE *fp);
int fputc(int c, FILE *fp);
int putchar(int c);
        All three return: c if OK, EOF on error

5 每次一行IO

#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

fgets必须指定缓冲区长度n。此函数一直读到下一个换行符为止,但是不超过n-1个字符,缓冲区以null字符结尾。gets不推荐,因为没有指定缓冲区大小,可能导致溢出。

#include <stdio.h>
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是将一个以null字符结尾的字符串写到指定的流,null不写出。通常null之前是换行符,但并不总是如此。

6 二进制流

通常用来读取数据结构struct,C语言书中提到过的。

#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

(1)ptr:是一个指针,对fwrite来说,是要获取数据的地址; (2)size:要写入内容的单字节数; (3)nobj:要进行写入size字节的数据项的个数; (4)fp:目标文件指针; 这些函数有如下两种常见用法(二进制数据或者结构体)

float data[10];
if (fwrite(&data[2], sizeof(float), 4, fp) != 4)
    err_sys("fwrite error");
struct {
      short   count;
      long    total;
      char    name[NAMESIZE];
} item;
if (fwrite(&item, sizeof(item), 1, fp) != 1)
   err_sys("fwrite error");

但是由于系统环境不同可能无法工作 (1)在一个结构中,同一个成员的偏移量可能因编译器和系统而异 (2)用来存储字节整数和浮点值的二进制格式在不同的机器体系结构间也可能不同

7 格式化IO

#include <stdio.h>
int printf(const char *restrict format, ...);
int fprintf(FILE *restrict fp, const char *restrict format, ...);
        Both return: number of characters output if OK, negative value if output error

int sprintf(char *restrict buf, const char *restrict format, ...);
int snprintf(char *restrict buf, size_t n, const char *restrict format, ...);
        Both return: number of characters stored in array if OK, negative value if encoding error

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Vue.js 如何使用 Socket.IO ?

    在很多需求业务中,都需要浏览器和服务器实时通信来实现功能,比如:扫码登录(扫码后,手机确认登录,PC网页完成登录并跳转)、订单语言提醒等,这些都是建立在两端实时...

    Javanx
  • PHP系列 | PHP跨平台实时通讯框架 Socket.IO 的应用

    利用PHP构建能够在不同浏览器和移动设备上良好运行的实时应用,如实时分析系统、在线聊天室、在线客服系统、评论系统、WebIM等。

    Tinywan
  • 20 Python 基础: 重点知识点--网络通信进阶知识讲解

    其他文章均已发表,可通过 “技术专栏 -- Python -- PY基础” 进行阅读。

    小Gy
  • 丑low的聊天室

    笔者第一次上网,学校网络室给定制的首页是一个红泥巴的聊天室。这回去看了下,卧槽还没倒闭:

    一粒小麦
  • kubernetes 下实现socket.io 的集群模式

    socket.io 单节点模式是很容易部署的,但是往往在生产环境一个节点不能满足业务需求,况且还要保证节点挂掉的情况仍能正常提供服务,所以多节点模式就成为了生成...

    domain0
  • 20 Python 基础: 重点知识点--网络通信进阶知识讲解

    本文首发于腾讯云+社区,也可关注微信公众号【离不开的网】支持一下,就差你的关注支持了。

    小Gy
  • 你可能不知道的浏览器实时通信方案

    这里以sockjs作为切入点,这是一个流行的浏览器实时通信库,提供了’类Websocket’、一致性、跨平台的API,旨在浏览器和服务器之间创建一个低延迟、全双...

    _sx_
  • socktIo的客户端与nodejs服务器端代码示例

    喜欢本文请扫下方二维码,关注微信公众号: 前端一会,查看更多我写的文章哦,多谢支持。

    前端_AWhile
  • Todo List: Socket.io多人协同处理待办事项 – 第七章(第二节)

    Todo List项目已经接近尾声,很多地方都没有细致的讲解,基本都是以简洁为主,快速的完成一个简单的demo。希望能给小伙伴们带来一些帮助。

    Javanx

扫码关注云+社区

领取腾讯云代金券