結論:大文本文件,遠超內存,須要格外注意。python
前言
生產服務器中常常產生不少文件,有些積年累月單個文件,體積愈來愈大。程序員
本文使用多種編程語言,實現大文件的讀取。express
PHP的處理方式
大文件若是直接open,就會被整個寫入內存,內存是吃不消的。好比4G的內存,10G的文件,這是處理不了的。也沒有哪一個文本編輯器能夠用。
編程
經常使用的file_get_contents函數,是將文件內容讀入到字符串變量內。而字符串變量分配在內存,因此沒有任何辦法處理大文件。vim
通常的作法是使用 fgets 函數。該函數從文件內讀取一行。函數格式以下:服務器
string fgets ( resource [, int ] )
其中參數 $handle 是文件指針,從 $handle 指向的文件中讀取一行並返回長度最多爲 $length - 1 字節的字符串。微信
碰到換行符(包括在返回值中)、EOF 或者已經讀取了 $length - 1 字節後中止(看先碰到那一種狀況)。若是沒有指定 $length,則默認爲 1K,或者說 1024 字節。less
實際用起來像下面這樣。編程語言
此函數效率極高,一次最多讀一行。而碰到整個文件都是一行的狀況,則按照設定的 $length 按照長度依次讀取。編輯器
Python的方式
從上述PHP的處理方法能夠看到,關鍵點是按行讀取,再按長度讀取。python的處理方法同樣,只是摻雜了一些語法糖。
python有一個「生成器」,解決大文件的讀取,就靠這個玩意兒。
在python的函數(function)定義中,只要出現了yield表達式(Yield expression),那麼事實上定義的是一個generator function, 調用這個generator function返回值是一個generator。
爲何genetor效率高呢,由於其與普通函數的有區別:
function每次都是從第一行開始運行,而generator從上一次yield開始的地方運行。
function調用一次返回一個(一組)值,而generator能夠屢次返回。
function能夠被無數次重複調用,而一個generator實例在yield最後一個值或者return以後就不能繼續調用了。
下面是使用帶有yield關鍵字的讀取大文件方法。
其實python還有更優雅便捷的寫法,就是for循環讀取。像下面這樣:
或者不用從新定義函數,直接用for循環遍歷。
底層使用的原理是同樣的。
Golang的方式
Golang的想法也同樣,它毫不把整個文件寫入內存。bufio庫就是讀寫文件的利器。
很少解釋,直接上示例。
Golang爲了統一場景,不管廣泛的和特殊的,都考慮在內了。這就是bufio的厲害之處。
對於讀寫,數據被存儲直到達到特定大小,經過這種方式觸發的寫操做更少。同時還減小了 sycall(系統調用)的數量,卻可使用更高效的方式使用底層硬件。
Linux下的工具
若是你在Linux處理該文本,那這徹底不是問題。自帶的不少工具,可以幫你處理這個簡單的問題。好比 head,讀取某文件的前多少行;tail,讀取某文件的最後多少行。
若是隻是要讀文件,那麼 less 是你最佳的選擇。
文檔內說的很清楚,less並不直接讀入整個文檔,所以處理起來,比vi/vim編輯器速度快的多。
打開以後,就能夠上下翻頁閱讀了。
結語
本文經過多種編程語言,實現了大文件的讀取。
掌握核心的方法後,使用哪一種語言實現,均可以。
【本文由 @程序員小助手 發佈,持續分享編程與程序員成長相關的內容,歡迎關注】
本文分享自微信公衆號 - 程序員小助手(mql45ea)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。