標題有點開玩笑,但大多數語言在檔案處理方面都沒怎麼用心思考。檔案操作總感覺有點格格不入……除了 C 語言。事實上,你通常得到的只是一個比 C 語言更糟的版本。
在 C 語言中,檔案可以像記憶體一樣被存取:
記憶體映射與將檔案載入記憶體不同:即使檔案不適合放入 RAM,它仍然有效。資料會根據需要載入,因此開啟一個 TB 大小的檔案不會花費一整天。
它適用於所有資料類型,並且會自動快取。如果系統需要記憶體來處理其他事情,這個快取就會被清除。
mmap() 實際上是一個作業系統功能,因此許多其他語言也擁有它。然而,它幾乎總是僅限於位元組陣列:你必須抓取一個資料塊,解析、處理,然後在寫回磁碟之前將其序列化。這比手動呼叫 read() 和 write() 要好一些,但好不了多少。
這些語言擁有所有這些在記憶體中操作資料的便利功能,但卻沒有任何用於操作磁碟上資料的功能。在記憶體中,你可以獲得動態大小的字串和向量、列舉類型、物件等等。在磁碟上,你只得到……一堆位元組。
考慮到大多數語言已經支援自訂配置器等功能,添加一種更好的檔案存取方式似乎是可行的,但卻沒有人真正這樣做。對我來說,C 語言——一個以不符合人體工學著稱的語言——實際上在這方面做得最好,這非常奇怪。
C 語言的實現甚至不是非常優秀:記憶體映射會帶來一些額外開銷(頁面錯誤、TLB 刷新),而且 C 語言並未處理位元組順序或錯誤……但總比沒有好。
當然,你可能想進行一些解析和驗證,但這不應該在每次資料離開磁碟時都必須進行。RAM 比磁碟小得多,因此經常無法將所有內容解析到記憶體中。
許多檔案並非不受信任的資料。
對於二進位檔案,解析通常是多餘的。程式碼沒有理由不能直接操作磁碟上的表示,對於「臨時記事本」類型的暫存檔案,可以儲存資料在 RAM 中的樣子。當然,你可能不想直接操作 JSON,但也沒有理由為了儲存一些整數而做大量工作。
檔案操作也同樣被忽視。檔案系統是最初的 NoSQL 資料庫,但你很少能得到比 C 語言 readdir() 包裝器更多的東西。
這通常導致人們在檔案系統之上運行另一個資料庫,例如 SQLite,但關聯式資料庫從未完全適合你的程式。
……而 SQL 的整合比檔案更差:除了必須序列化所有資料之外,你還必須編寫一種完全獨立的語言來存取它!
大多數程式設計師會將其用作鍵值儲存,並實現自己的索引:創建一個奇特的 ट्रिपल嵌套資料庫。
所以,要回答標題的問題,我認為這是由於一個錯誤的假設:從檔案讀取的資料來自其他地方,需要被解析……寫入磁碟的資料被發送到某處,需要被序列化為標準格式。
這在記憶體受限的系統上根本不成立——而且對於 100 GB 的檔案來說——每個系統都是記憶體受限的。