如何理解編程語言中「流」(stream)的概念?

在 Java 相關的資料中這麼說:

An object from which we can read a sequence of bytes
is called an input stream. An object to which we can write a sequence of
bytes is called an output stream.

意思應該是在面向對象中流就是對象,可以從這個對象讀位元組序列(輸入流)或者寫位元組序列(輸出流)。

而在學 C 的時候,說流就是位元組序列。

感覺這兩種對流的解釋差別特別大,是因為面向對象造成的差異嗎?


這個問題可以從這個角度回答:

為什麼要有流?

假設沒有流, 所有的數據都可以用二進位串來表示, 也沒什麼的呀. 我們再簡單點, 就認為那是string. 假設我寫了一個html的parser:

def html_parse(html_string):
// do magic
return html_tree

可是我們可能是從網路獲得 html_string 的, 大家都知道網路相比於CPU的速度那就很慢了, 我們希望能夠邊獲得數據, 邊解析數據, 充分利用CPU, 那麼我們可能會這樣寫

parser = Parser()
while not is_net_done():
bytes = read_little_from_net()
parser.parse_little(bytes)
print parser.tree

也就是, 我們會從網路裡面讀一點, 解析一點.

類似的需求很常見, 比如播放視頻的時候, 我們肯定是希望從硬碟(或者網路)讀取一點, 播放一點, 一個視頻4GB, 要是全部載入內存才能播放, 好多人都看不成1080p的了.

所以, 我們有充分的理由把這種讀一點處理一點(以及相反的生成一點, 寫入一點)的數據類型(或曰操作)抽象出來, 這就是流.

至於其實現原理, 就實在太簡單, 而且多種多樣, 不講了.

你只要記住: 流就是讀一點數據, 處理一點點數據. 就可以了.


現有答案很多人說的是用來存放數據的Stream吧?但我更傾向於這是類庫或執行環境中的數據流概念,而不是編程語言里的概念。這種「流」的典型代表好比Java里的InputStream,OutputStream。

而說起編程語言里的Stream,我認為應該說是一種「延遲執行」的序列構造,典型代表是Java 8里java.util.stream的那些東西。隨手搜了一些資料:

Functional Programming - Streams

還可以去Coursera上面看Programming Languages課程,用Racket講過Stream。

Racket Documentation - 4.14.2 Streams

PS:回答後發現題主補充了詳細說明,原來要的就是「數據流」。真是豈有此理,那就當我沒說吧……


Scala中的Stream

object Stream {
def cons[T](hd: T, tl: =&> Stream[T]) = new Stream[T]{
def isEmpty = false
def head = hd
def tail = tl // t1不立即計算的
}
.....
}

可以作延時計算的.

PS:回答後發現題主補充了詳細說明,原來要的就是「數據流」。真是豈有此理,那就當我沒說吧…… --- @趙劼


一切能被讀寫的都是文件,流是讀寫文件的抽象;其實這個概念在 unix 和 plan9 體現得非常嚴重


`A Stream Input/Output System", from ATT Bell Laboratories Technical Journal, 1984


A very important concept in C is the stream. In C, the stream is a common, logical interface to the various devices that comprise the computer.

In its most common form, a stream is a logical interface to a file. As C defines the term "file", it can refer to a disk file, the screen, the keyboard, a port, a file on tape, and so on.

Although files differ in form and capabilities, all streams are the same. The stream provides a consistent interface and to the programmer one hardware device will look much like another.

參見The Stream File

C programming Interview questions and answers: What is stream in c programming language?

所以,流(stream)是一種面向多設備的(通常是文件(file))的邏輯的介面(logical interface)


流(Stream)就是指像水流一樣長長的一串的東西。

在很多時候,流(Stream)是位元組流(Byte Steram)的簡稱,也就是長長的一串位元組,,,,

當然,除了位元組流,我們還可以有視頻流、音頻流、數據流,,,,

流只有一個特徵就是連續,流可以沒有頭可以沒有尾,甚至可能沒有絕對的位置(因為無頭無尾),但是由於流是連續的,所以有相對位置。

流是一個很抽象的概念,只有多用才能理解。

但是流絕對不是一個容器,這是一個典型的誤解。容器可以被視為一個流,或者可以用流的方式來讀寫,但流不是容器。

譬如說,網路流(NetworkStream)就不是一個容器,也正因為流不是一個容器,所以流不存在拷貝。我們可以拷貝文件,拷貝內存,但是不能拷貝一個流。

同理,標準輸入輸出流顯然也不是容器。

如果是說.NET Framework中的Stream對象,其實我覺得他更像一個設備(Device)。這個設備提供或者不提供三個方法:讀(Read )、寫(Write)、檢索(Seek),但是一個設備必須至少提供讀或者寫中的一個方法。


Streams as Lazy Lists

人家問的是編程語言裡面的Stream,你們扯什麼水流比特流?連SICP都沒讀過就別出來貽笑大方了,OK?

給除了 @趙劼@壯壯 以外的其他逗比答案點了反對+沒有幫助。


像水流的東西。一個抽象的概念。譬如說:

黃河之水天上來,奔流到海不復回

有源頭: 天上來

有方向:到海

有順序:奔流(後浪推前浪)、不復回

編程語言的流常常用來指: 位元組流、字元流等數據流

關注於的話,數據與水並沒有區別。

基本同意 @薛非的說法。


010011100100110101101101001000111101101010111010101010101011110101010101100100101010110101001010101010101010101000010111010110011110100110010100010011100100110101101101001000111101101010111010101010101011110101010101100100101010110101001010101010101010101000010111010110011110100110010100010011100100110101101101001000111101101010111010101010101011110101010101100100101010110101001010101010101010101000010111010110011110100110010100010011100100110101101101001000111101101010111010101010101011110101010101100100101010110101001010101010101010101000010111010110011110100110010100010011100100110101101101001000111101101010111010101010101011110101010101100100101010110101001010101010101010101000010111010110011110100110010100010011100100110101101101001000111101101010111010101010101011110101010101100100101010110101001010101010101010101000010111010110011110100110010100010011100100110101101101001000111101101010111010101010101011110101010101100100101010110101001010101010101010101000010111010110011110100110010100010011100100110101101101001000111101101010111010101010101011110101010101100100101010110101001010101010101010101000010111010110011110100110010100010011100100110101101101001000111101101010111010101010101011110101010101100100101010110101001010101010101010101000010111010110011110100110010100010011100100110101101101001000111101101010111010101010101011110101010101100100101010110101001010101010101010101000010111010110011110100110010100010011100100110101101101001000111101101010111010101010101011110101010101100100101010110101001010101010101010101000010111010110011110100110010100010011100100110101101101001000111101101010111010101010101011110101010101100100101010110101001010101010101010101000010111010110011110100110010100010011100100110101101101001000111101101010111010101010101011110101010101100100101010110101001010101010101010101000010111010110011110100110010100010011100100110101101101001000111101101010111010101010101011110101010101100100101010110101001010101010101010101000010111010110011110100110010100010011100100110101101101001000111101101010111010101010101011110101010101100100101010110101001010101010101010101000010111010110011110100110010100010011100100110101101101001000111101101010111010101010101011110101010101100100101010110101001010101010101010101000010111010110011110100110010100...

看不清裡面是什麼吧,就像水一樣就流過去了


就是邊生產數據,邊處理消費數據。從抽象上來看,就是流。例子,攝像頭數據採集等。


流是一個抽象的概念,很多人一看到流就講什麼位元組流,對象流,比特流……其實都是具體化了。當然,要理解抽象的東西必須有真實的對照,但是位元組、對象、比特本身就是比較抽象的東西,自然不易理解。讓我們來舉個實際點的栗子——工廠。

工廠有生產線,生產線上有工人(或者說機器人)。每個工人一般都是在一個固定的位置,對處於某個狀態的產品按指定的工序進行加工。

那麼,把生產線上的一個接一個的產品當成流(Stream),工人就是流處理器(Stream Wrapper/Filter,即加工或篩選),然後生產線上運輸產品的裝置(比如傳送帶)就是管道(Pipeline)。

流處理就是將數據處理模擬成工廠的生產線,每一道工序(wrapper)上都有特定的處理程序,處理好了就pipe到下一道工序。用偽代碼表示如下:

a.pipe(b).pipe(c).pipe(d); // ....

所以說流(Stream)是指數據(Data),而不是容器。流的容器是管道(Pipeline),即運輸裝置。流的本意是模擬水流的特性,水流從上游流動到下游,編程里的流也是一樣的。對於單個流處理器(工序)而言,上一個流處理器(工序)就是上游,下一個就是下游。

另外要提一下的是,編程裡面流一般有兩個工作模式:(以作為一個流處理器的視角)

一是「流動模式」,就是說數據源源不斷地從上游而來,你只要不斷地處理即可。但是每道工序消耗的時間不同,如果你處理不過來,數據就累積在你的緩衝區裡面,越來越多,直到你的緩衝區爆掉;(相當於 Push 模式)

二是「非流動模式」,數據也會來,但是你要手動從流中提取數據,你不提取數據就存留在上游的發送緩衝區里,最後上游的發送緩衝區爆掉了。(相當於 Pull 模式)

因此實現流也要考慮流的「溢出」。


這兩天也是在迷糊這個問題,(C++流到底是什麼東西-CSDN論壇-CSDN.NET-中國最大的IT技術社區)這裡面看到一個回答很符合我的問題。如下:

C++流是指信息在內存和外部設備之間傳遞(流動)的過程。

標準I/O流:內存與標準輸入輸出設備之間信息的傳遞;

文件流:內存與外部文件之間的信息傳遞;

字元串流:內存變數與表示字元串流的字元數組之間信息的傳遞。

我理解的關鍵是第一句。


我在另一個問題下的回答 https://www.zhihu.com/question/38075755/answer/233146972


位元組構成

有頭有向有序

有入有出無尾

==================

「無尾」的說法可能會有爭議

靜待。


跟「水流」其實差不多的。

水流流的是水分子。

這個流流的是位元組/比特/電平而已。

比特/電平可以理解為原子,若干個原子按照一定的數量規律組成分子/位元組,不同的分子/位元組由於其構成差異,人們又賦予其不同的信息含義。比如H2O,H2O2,這個位元組代表A,另外個位元組代表C。

很多分子/比特源源不斷的傳輸,就形成了流(stream).


推薦閱讀:

boost或C++11中的bind怎麼自己實現?
如何正確理解boost::any的設計?
CUDA中可以用什麼來替代Vector類?
C++基本的知識都有了,但是很少C++解決問題,怎麼提高自己的實踐能力?
此處的C++斐波那契數列是如何實現的?

TAG:編程語言 | C編程語言 | C | 編程學習 |