為什麼C++中會把文件操作抽象為fstream?

為什麼要把文件操作抽象為數據流?

「指程序與數據的交互是以流的形式進行的」,」數據流「這種說法是從何而來?

除了數據流,還有別的交互形式?


文件抽象為數據流一定程度上是 Unix 造成的。

傳統上,計算機上用於 IO 的設備大致可以分成兩大類,塊(block)設備和流(stream)設備。前者可以抽象成一組數據塊,讀寫必須數據塊為單位,但一般可以指定任意一個數據塊讀寫,典型的例子比如磁碟,以扇區為單位進行讀寫。後者可以抽象成一個數據流,你可以一個位元組一個位元組的讀寫,但寫出去的數據就是寫出去了,沒法再改,典型的例子比如串口,發出去一個位元組那就是發出去了。

然後呢,Unix 有個概念上很好、實踐中時不常要坑爹的設計,「一切 IO 皆文件」(Everything is a file)。換句話說,一個「文件」背後可能是個塊設備,也可能是個流設備 …… 顯然,塊設備模擬流設備很容易,反之則幾乎不可能,所以深受 Unix 影響的 C/C++ 在操作文件的 api 上都傾向於數據流模型 —— 這不單是 C++ 的 iostream,仔細感受下 C 的 fscanf / fprintf / fputs ……

至於其他的數據交互模型,思路打開一點就會發現到處都是啊!這裡只舉一個例子:一個程序怎麼讀寫資料庫里的數據呢?

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

修訂:「流設備」的名稱有誤,正確的名稱是「字元設備」。感謝 @Sam Liao 的指正!


想想這兩種情況即可:

  • 有些文件在空間上太龐大,無法一次性全部載入進內存(如:無窮大的文件)
  • 有些文件在時間上不連續,無法一次性全部載入進內存(如:標準輸入、Socket)

p.s. 「時間上不連續」有點文不達意,可以理解為只有在未來才能得到完整的數據……


這不過是返祖罷了。正確的問題是為什麼會把數據流抽象成文件。


因為夠用了。

一般的程序不需要對文件進行隨機存取。比如記事本程序,保存文檔的時候是將文件清空,然後重新寫入磁碟。還有類似的程序有遊戲存檔、瀏覽器下載文件、Photoshop、Word、Excel、PPT等,它們在操作文件的時候都是將文件清空再重新寫入,特點都是文件尺寸比較小,對文件整體讀寫也不影響性能。

有些特殊的程序確實需要隨機存取,比如:資料庫、下載工具(比如迅雷)、視頻播放(在拖動進度條的時候)。這些程序的特點都是文件尺寸比較大,不方便對文件進行整體讀寫。


你的問題主要在於編碼不多而想得太多。

你多寫寫幾個與文件打交道的小程序自然就明白了。


文件本身就是個抽象的概念.

既包括可隨機存取的普通文件,也包括串口這樣的順序訪問的文件.

別的方式最典型的就是內存影射 mmap


引用《面向對象程序設計——C++語言描述》上的一段話:

「在C++中,程序的輸入被看作從鍵盤、磁碟文件或其他輸入源輸入的一串連續的位元組流;程序的輸出被看作是輸出到顯示器、磁碟文件或其他目標的一串連續的位元組流。因此C++輸入/輸出也被稱作輸入/輸出流。」

感覺本回答純屬文字遊戲。嗯。我純粹是打醬油的。

實不相瞞,年輕人,你這個問題提到的「流」讓我陷入了對時間、空間的深深思索中……


內存是隨機存儲。文件其實也可以是隨機存儲,只是很多存儲設備裡面文件做隨機存儲其實不是natively support的。

UDP是block,TCP是stream

Named Pipe有message模式也有stream模式

等等


如果樓主是要問 為什麼C++要這麼做: 因為C++的fstream是繼承於C++標準的iostream,是對C++標準庫順理成章的"延續", 有利於標準化。

如果樓主是要問 為什麼要抽想成一個stream:我覺得一方面是習慣,另一方面stream的介面滿足絕大多數文件操作需求。

如果樓主是要問 為什麼要用fstream這個名字: 是個比喻吧, 像水流 ~~~ :)


Linux 設備分為字元(c)和塊(b)設備兩種。tty 是 c 設備,不能 seek,「流」是正確的抽象;C 的 stdin / stdout 操作介面大致就是喂這種用例設計的,C++ 順著一路抄下來了而已。

不使用 seek 基本上做不了多少有用的事情;seek 本身又不是一個可以映射到「流」上去的操作。

所以……

When should I use mmap for file access?

對於嚴肅的文件操作的場合,mmap 才是王道。fstream 什麼的……呵呵。


因為當初機械磁碟讀文件是順序讀取的,現在ssd磁碟可以隨機讀,但大多數場景還是順序讀的


推薦閱讀:

為什麼 Python 3.0 設計成不與 Python 2.X 兼容?主要有哪些地方需要突破才導致這一決定?
怎樣才叫 「精通」 C語言?
有沒有合適的學習路線來學習封裝在IDE下的原理?
如何開發中文演算法?
各種常見的編程語言最廣泛應用的領域分別是什麼?

TAG:編程語言 | 計算機科學 | C | 編程理論 |