C语言中的“stream”是什么意思?

20
我正在阅读《C Primer Plus》一节关于文件、流和键盘输入的内容。作者将流的概念与文件联系起来,并定义流如下:

在概念上,C程序不是直接处理文件而是处理流。流是被映射为实际输入或输出的抽象数据流。这意味着具有不同属性的各种输入通过具有更统一属性的流来表示。打开文件的过程就变成了将流与文件相关联,而读写则通过流进行。

作者粗体字句子的意思是什么?文件与流之间有什么联系?

在互联网上搜索并阅读有关C语言文件流的各种其他来源,如tutorialspoint.com等,您将会理解它。 - 0xF1
1
你已经用粗体标记了答案。那就是它的答案。毕竟不是一个坏问题,但我怀疑它是否属于这里。 - sjsam
2
也许你可以将它想象成一根管道(一根传输水的管子)- 一种通过其中流入和流出数据的连接。 - abhishek_naik
@BatCoder 你所说的 pipe 是什么意思? - Jin
1
@Don'tYouWorryChild,在编程或与之相关的任何内容上阅读教程点是你应该去的最后一个地方。 - qwr
6个回答

29
注意,文件和流是非常不同的东西。文件只是字节序列,而流只是辅助工具。
流出现的原因是因为所有程序都需要以许多不同的形式与其周围环境进行交互(可能是文件,可能是I/O设备,如显示器和键盘,可能是网络套接字等)。
因此,流是一个接口(一种易于使用的“面孔”,用于处理我们无关紧要的许多细微差别,就像我们不需要知道电视遥控器的工作原理!),用于触发数据的输入/输出流,从/到可以成为该输入/输出数据源/目标的任何内容,隐藏了操作系统为代表程序员与各种设计良好的硬件进行交互而设计的众多方法的低级实现细节(即,作为程序员,我们并不真正关心每次创建新软件时操作系统与各种硬件进行交互的重新编程方式)。
因此,比如考虑我们的程序如何从键盘获取输入...这是怎么发生的呢?这是通过一个隐藏的(对程序员来说隐藏的)流程来实现的,操作系统为每个“进程”提供(一旦启动程序,它就被称为进程),并且操作系统将标准流程的地址自动分配给该进程(即,我们不需要编写代码来查找其地址)。这个流通常称为“stdin”(源于C和Unix术语),或更正式地称为“标准输入流”。我们的程序,无论用什么语言编写,都必须能够通过该语言的标准I/O库使用操作系统创建的这种标准流。作为示例,在C编程语言中,我们可以通过调用函数“scanf”(scanf会自动知道我们程序的stdin在哪里)来扫描标准输入流。
但是作为另一个重要的例子,再次涉及C语言,假设这一次我们的程序想要将用户输入写入到“文件”中...仅仅stdin流的存在是否足够?当然不是!这一次,我们需要使用一对流,一个已经由操作系统提供的stdin来获取用户的输入,另一个则用于让我们的程序与文件进行通信!因此,我们将需要创建第二个流!这可以通过调用fopen()函数来完成。 (有趣的事实:在手册中,如果你注意到,你会看到这个函数的返回类型是一个指向称为FILE的结构体的指针,但那只是传统的“不恰当的词汇选择”,实际上它是指向一个“流”的指针!是的,C语言中的FILE类型确实是一个流,而不是一个文件!(我知道,很疯狂!)所以请记住,指针FILE*并不指向实际的文件,而是指向包含该文件信息的流,包括用于文件I/O的缓冲区等信息。)
注意:我们自己创建的流(例如文件流)可以是双向的,而标准流是单向的。下面的图片很好地说明了这一点: enter image description here 此外,作为一个在C++世界中的例子,你知道在那里,东西都在类中而不是结构体中,所以如果你要输出,你会遇到一个名为“cout”的对象(输出流对象),它是连接到输出流(stdout在C中)的对象,并且是类ostream的一个实例(从类层次结构ios_base <-- ios <-- ostream)。要使用cout写入标准输出流,必须使用它的“<<”方法(对应于C中的printf())。这次再次提醒一下,cout不能满足与其他事物(如文件)交互的需求,我们需要创建自己的流。在C++中,可以通过实例化ifstream和ofstream类(对应于C中的FILE结构)来实现这一点,这将导致基本上扮演指针“FILE*”在C中的角色的对象。
希望这有所帮助。

图片来源于linuxhint.com


@M-S,你提到了“从键盘输入”,这是怎么实现的?并且还有明确的“stdout”。为什么是输出?你应该使用输入流“stdin”吧? - Jin Lim
@JinLim 确实是个错误,感谢您指出,我已经在编辑中修复了它。 - M-J

23

设计C语言的人希望能够有一种统一的方式来接口不同来源的顺序数据,例如文件、套接字、键盘、USB端口、打印机或其他设备。

因此,他们设计了一个可以应用于所有这些设备的接口。该接口使用这些设备所共有的属性。

为了更方便地谈论可以通过接口使用的东西,他们给这些东西起了一个通用名称——流(streams)

使用相同的接口的优美之处在于,相同的代码可用于从文件、键盘或套接字中读取数据。


1
流本质上是一个文件吗?(只是出于好奇) - aderchox
7
什么是文件?文件是一种抽象概念。它是内存中某个地址,指示一系列字节的第一个字节(如果是大型文件,则可能会分段)。流也是一个内存位置,在其中写入字节并读取字节。在这个意义上,它类似于文件,因为您可以从中写入和读取数据。但它们都是抽象的。它们只是内存偏移量,可以从中读取和写入数据。 - Daniel
流是操作系统级别还是C语言级别的概念? - xusisme

5

流(Stream)是一个逻辑实体,代表一个可以接受输入和输出的文件(File)设备(Device)。在标准C中,所有输入和输出函数都操作于数据流上。流可以分为文本流二进制流


1

简单来说,流就是一个文件指针 FILE * 就像 C 语言中的函数 FILE * fopen ( const char * filename, const char * mode ) 这个函数返回一个文件指针 File *

文件:

包含控制流的信息的对象 标识流并包含控制它所需的所有信息的对象类型,其中包括指向其缓冲区、位置指示器和所有状态指示器的指针。


0

我的 C 编程学位使用以下内容作为解释,如果有帮助的话: “流是文件的抽象,为程序员提供了一致的接口,而不管实际设备如何。”


0

流是处理不同数据媒介/来源的C语言方式。这些可以包括:

  1. 文件
  2. 套接字

等等。作为一种接口,流帮助您忘记底层数据如何管理并集中精力于所需目标。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接