讀取超級大的單個文件,用這個方法一招搞定,你必定用的着。

結論:大文本文件,遠超內存,須要格外注意。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效率高呢,由於其與普通函數的有區別:

  1. function每次都是從第一行開始運行,而generator從上一次yield開始的地方運行。

  2. function調用一次返回一個(一組)值,而generator能夠屢次返回。

  3. 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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索