PHP超低記憶體遍歷目錄檔案和讀取超大檔案的方法

2022-09-26 05:39:11 字數 2280 閱讀 6801

這不是一篇教程,這是一篇筆記程式設計客棧,所以我不會很系統地論述原理和實現,只簡單說明和舉例。

前言我寫這篇筆記的原因是現在網路上關於 php 遍歷目錄檔案和 php 讀取文字檔案的教程和示例**都是極其低效的,低效就算了,有的甚至好意思說是高效,實在辣眼睛。

這篇筆記主要解決這麼幾個問題:

php 如何使用超低記憶體快速遍歷數以萬計的目錄檔案?

php 如何使用超低記憶體快速讀取幾百mb甚至是gb級檔案?

順便解決哪天我忘了可以通過搜尋引擎搜到我自己寫的筆記來看看。(因為需要 php 寫這兩個功能的情況真的很少,我記性不好,免得忘了又重走一遍彎路)

遍歷目錄檔案

網上關於這個方法的實現大多示例**是 glob 或者 opendir + readdir 組合,在目錄檔案不多的情況下是沒問題的,但檔案一多就有問題了(這裡是指封裝成函式統一返回乙個陣列的時候),過大的陣列會要求使用超大記憶體,不僅導致速度慢,而且記憶體不足的時候直接就崩潰了。

這時候正確的實現方法是使用 yield 關鍵字返回,下面是我最近使用的**:

<?php function glob2foreach($path, $include_dirs=false) /";

if (is_dir($rfile))

if ($include_dirs)

yield $rfile;

} else

}closedir($dh);

}}// 使用

$glob = glob2foreach('/var/www');

while ($glob->valid())

yield 返回的是生成器物件(不了解的可以先去了解一下 php 生成器)utwqyh,並沒有立即生成陣列www.cppcns.com,所以目錄下檔案再多也不會出現巨無霸陣列的情況,記憶體消耗是低到可以忽略不計的幾十 kb 級別,時間消耗也幾乎只有迴圈消耗。

讀取文字檔案

讀取文字檔案的情況跟遍歷目錄檔案其實類似,網上教程基本上都是使用 file_get_contents 讀到記憶體裡或者 fopen + feof + fgetc 組合即讀即用,處理小檔案的時候沒問題,但是處理大檔案就有記憶體不足等問題了,用 file_get_contents 去讀幾百mb的檔案幾乎就是自殺。

這個問題的正確處理方法同樣和 yield 關鍵字有關,通過 yield 逐行處理,或者 splfileobject 從指定位置讀取。

逐行讀取整個檔案:

<?php function read_file($path)

fclose($handle);

}}// 使用

$glob = read_file('/var/www/hello.txt');

while ($glob->valid())

通過 yield 逐行讀取檔案,具體使用多少記憶體取決於每一行的資料量有多大,如果是每行只有幾百位元組的日誌檔案,即使這個檔案超過100m,占用記憶體也只是kb級別。

但很多時候我們並不需要一次性讀完整個檔案,比如當我們想分頁讀取乙個1g大小的日誌檔案的時候,可能想第一頁讀取前面1000行,第二頁讀取第1000行到2000行,這時候就不能用上面的方法了,因為那方法雖然占用記憶體低,但是數以萬計的迴圈是需要消耗時間的。

這時候,就改用 splfileobject 處理,splfileobject 可以從指定行數開始讀取。下面例子是寫入陣列返回,可以根據自己業務決定要不要寫入陣列,我懶得改了。

<?php function read_file2arr($path, $count, $offset=0)

return $arr;

}以上所說的都是檔案巨大但是每一行資料量都很小的情況,有時候情況不是這樣,有時候是一行資料也有上百mb,那這該怎麼處理呢?

如果是這種情況,那就要看具體業務了,splfileobject 是可以通過 fseek 定位到字元位置(注意,跟 seek 定位到行數不一樣),然後通過 fread 讀取指定長度的字元。

也就是說通過 fseek 和 fread 是可以實現分段讀取乙個超長字串的,也就是可以實現超低記憶體處理,但是具體要怎麼做還是得看具體業務要求允許你怎麼做。

複製大檔案

順便說下 php 複製檔案,複製小檔案用 copy 函式是沒問題的,複製大檔案的話還是用資料流好,例子如下:

<?php function copy_file($path, $to_file) }最後

我這只說結論,沒有展示測試資料,可能難以服眾,如果你持懷疑態度想求證,可以用 memory_get_peak_usage 和 microtime 去測一下**的占用記憶體和執行時間。

本文標題: php超低記憶體遍歷目錄檔案和讀取超大檔案的方法

本文位址:

PHP遍歷目錄和檔案列表

php view plain copy define ds directory separator class getdirfile closedir handle else return dirarray 獲取檔案列表 public function getfile dir closedir ha...

C C 遍歷檔案和目錄

c c 遍歷資料夾要用到 finddata t結構體,函式 findfirst findnext和 fineclose,它們都定義在標頭檔案中,下面介紹具體如何使用.結構體 finddata t是用來儲存檔案各種資訊的,其中成員變數分別為 unsigned atrrib 檔案屬性的儲存位置,它儲存乙...

使用PHP遍歷檔案目錄與清除目錄中檔案的實現詳解

今天無聊中練習了一下php遍歷檔案目錄的程式,編寫了以下兩個程式,不過質量不是很好,輕拍 1 清除php快取檔案 複製 如下 function read dir dir,file if strpos file,0 strpos file,false return true if strpos fil...