BSP Day 29

BSP Day 29,第1张

c语言中的流

  “流是磁盘或其它外围设备中存储的数据的源点或终点。”。这是在《C程序设计语言》上的原话。

据我的理解,流主要是指一种逻辑上的概念,它提供或存储数据。产生数据的叫输入流,消耗数据的叫输出流。至于怎么产生,又怎么消耗,这是一种物理上的实现,根据每种设备有所不同,但C语言中对它们一视同仁,以一个“流”字来概括它们的特征。作为流的使用者来说,不需要关心太多的细节。流的实现保证了它具有它所声明的特性。C语言中对流除了分为I/O流之外,还分为文本流与二进制流。文本流的特点是流由文本行组成,每一行有0个或多个字符并以’\n’字符结束,即它是有一定意义的,以某种字符集的字符组成的一个序列。一个文本流,读入与写出时可能会对其内容作更改,因为它是有一定意义的,系统可以识别并在适当时候解释,比如在输出文本流中碰到’\b’时,系统的 *** 作是将输入流中的前一个字符删除,在终端上显示就是在它前面输出的这个字符被删除了;二进制流则完成是由一些“生”的,未经处理的数据组成的,C语言将它们看成由0与1组成的序列来读与写,所以它们的特性是同一系统中把同一二进制流读入与写出,其内容没有任何变化。

如果你写的是个复制文件的程序,就是把一个存在的文件复制一遍再给回去。那么问题来了,谁给你的程序那个需要被复制的文件(从哪儿输入)?你复制完了交给谁(输出到哪儿)? 复制一句返回一句还是全部复制完再一起返回?用文本交流还是用电脑喜欢的二进制交流?C语言就是用流来回答这些问题的。

流被定义成指针,指针就是地址嘛。拿输入来说,stdin就是默认的输入流,通常就是键盘输入。啥意思?就是没有特别说明的话,你的程序就是找键盘要那个需要被复制的文件。stdin就是一个指向键盘这个输入设备的指针。针对这个stdin这个指针,又有对应的函数来执行相印的 *** 作,如果输入的是字符,就用getchar,文本用gets,scanf,二进制数据用fread。 理解了这一个流,其他就同理了。

再类比一下人的场景。你是个有生意头脑的人,你发现很多同学不喜欢写作业,你恰好又喜欢写作业。于是你弄了个业务,就是帮忙抄作业(这个业务相当于程序功能)。为了多赚钱,不把时间浪费在收集同学们希望你帮忙的作业上,你在你的宿舍门口放了一个箱子,需要你做的作业直接丢那个箱子就好了(这就算默认输入的来源,这个箱子就相当于键盘),你做作业的时候是按规律一本一本拿,做完一份再去拿一份(一份一份持续输入形成输入流,而不是做完一份就不处理下一份)。如果是薄薄的试卷,你喜欢用镊子夹过来处理;如果是本子,你喜欢用手抓过来处理,(这个方式就是对应的函数如何处理流)。

再来回头看看输入流的要素(本质),指针指向来源,根据来源的数据结构选择对应的 *** 作函数,指针在来源内部依次流转形成输入流直至输入完成。

流这个定义非常的形象。

你声明一个FILE *fp ,并把fopen(某个文件)返回的值赋予fp这两个动作就相当于建立了一个水龙头,

当你用getc(fp)之类的输入函数读取文件字符时就相当于拧开了水龙头,每读取一个字符,这个文件就像水一样的流动一下,fp所指的地址自然就向后移动了一位。

int ch;

while((ch=getc(fp))!=EOF)

putchar(ch);

你看这个循环,可以读取一个文件的所有字符。如果不是流的话,ch永远是第一个字符,不会更新。也可以理解为,fp自动++(一个字符的大小)。

一句话,流是文件描述符的抽象,一般使用文件描述符是系统层次的调用。

当向一个文件读入或者输出时,既可以选择流,也可以选择使用文件描述符。文件描述符是int类型的,而流是用FILE *来表示的。

文件描述符提供了一个原始、低层次的输入输出接口。文件描述符和流都可以表示一个连接,可以是和设备的(例如终端),或者管道,或者一个和另一个进程的套接字,或者就是一个正常的文件(normal file)。但是,如果你想要对特殊设备进行特定的 *** 作,你必须使用文件描述符。另外,如果你的程序需要以特殊模式进行输入输出(例如nonblocking, polled input, 参见File Status Flags),也必须使用文件描述符。

而流提供了一个基于原始的文件描述符的高层次接口。流接口对于所有类型的文件的 *** 作大多都是类似的,唯一的区别就是缓冲的策略(参见下面的流缓冲)。

使用流的主要优势是 *** 作流的函数比文件描述符多得多,而且更加强大方便。文件描述符仅仅提供了一个单一的函数用来传输字符块,但是流接口提供了很多格式化的输入输出(例如printf和scanf)和一些字符函数以及列读入输出函数。

因为流是基于文件描述符的,所以实际上你可以“拆解”一个流得到对应的文件描述符然后进行低层次的 *** 作。相反地,你也可以先用文件描述符和一个文件建立连接,然后建立一个链接这个文件描述符的流对象。

通常情况下,你都应该使用流来进行输入输出,这样不仅方便强大,而且可以保证程序的移植性:你可以在任何一个遵守ISO C标准的机器上使用流,但是在一个非GNU机器上你可能无法使用文件描述符。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/3002558.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-27
下一篇 2022-09-27

发表评论

登录后才能评论

评论列表(0条)

保存