国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 網(wǎng)站 > 建站經(jīng)驗(yàn) > 正文

PHP如何快速讀取大文件

2024-04-25 20:36:25
字體:
供稿:網(wǎng)友

在PHP中,對于文件的讀取時,最快捷的方式莫過于使用一些諸如file、file_get_contents之類的函數(shù),簡簡單單的幾行代碼就能 很漂亮的完成我們所需要的功能。但當(dāng)所操作的文件是一個比較大的文件時,這些函數(shù)可能就顯的力不從心, 下面將從一個需求入手來說明對于讀取大文件時,常用的操作方法。

需求需求

有一個800M的日志文件,大約有500多萬行, 用PHP返回最后幾行的內(nèi)容。

實(shí)現(xiàn)方法

1. 直接采用file函數(shù)來操作

由于 file函數(shù)是一次性將所有內(nèi)容讀入內(nèi)存,而PHP為了防止一些寫的比較糟糕的程序占用太多的內(nèi)存而導(dǎo)致系統(tǒng)內(nèi)存不足,使服務(wù)器出現(xiàn)宕機(jī),所以默認(rèn)情況下限制只能最大使用內(nèi)存16M,這是通過php.ini里的 memory_limit = 16M 來進(jìn)行設(shè)置,這個值如果設(shè)置-1,則內(nèi)存使用量不受限制。

下面是一段用file來取出這具文件最后一行的代碼:

<?phpini_set('memory_limit', '-1');$file = 'access.log';$data = file($file);$line = $data[count($data) - 1];echo $line;?>
整個代碼執(zhí)行完成耗時 116.9613 (s)。

我機(jī)器是2個G的內(nèi)存,當(dāng)按下F5運(yùn)行時,系統(tǒng)直接變灰,差不多20分鐘后才恢復(fù)過來,可見將這么大的文件全部直接讀入內(nèi)存,后果是多少嚴(yán)重,所以不在萬 不得以,memory_limit這東西不能調(diào)得太高,否則只有打電話給機(jī)房,讓reset機(jī)器了。

2.直接調(diào)用Linux的 tail 命令來顯示最 后幾行

在Linux命令行下,可以直接使用 tail -n 10 access.log 很輕易的顯示日志文件最后幾行,可以直接用PHP來調(diào)用tail命令,執(zhí)行PHP代碼如下:

<?php$file = 'access.log';$file = escapeshellarg($file); // 對命令行參數(shù)進(jìn)行安全轉(zhuǎn)義$line = `tail -n 1 $file`;echo $line;?>
整個代碼執(zhí)行完成耗時 0.0034 (s)

3. 直接使用PHP的 fseek 來進(jìn)行文件操作

這種方式是最為普遍的方式,它不需要將文件的內(nèi)容全部讀入內(nèi)容,而是直接通過指針來操作,所以效率是相當(dāng)高效的。在使用fseek來對文件進(jìn)行操作時,也有多種不同的方法,效率可能也是略有差別的,下面是常用的兩種方法:

方法一

首先通過fseek找到文件的最后一位EOF,然后找最后一行的起始位置,取這一行的數(shù)據(jù),再找次一行的起始位置, 再取這一行的位置,依次類推,直到找到了$num行。

#實(shí)現(xiàn)代碼如下

<?php$fp = fopen($file, "r");$line = 10;$pos = -2;$t = " ";$data = "";while ($line > 0){ while ($t != "/n") { fseek($fp, $pos, SEEK_END); $t = fgetc($fp); $pos--; } $t = " "; $data .= fgets($fp); $line--;}fclose($fp);echo $data?>
整個代碼執(zhí)行完成耗時 0.0095 (s)
方法二
還是采用fseek的方式從文件最后開始讀,但這時不是一位一位的讀,而是一塊一塊的讀,每讀一塊數(shù)據(jù)時,就將讀取后的數(shù)據(jù)放在一個buf里,然后通過換 行符(/n)的個數(shù)來判斷是否已經(jīng)讀完最后$num行數(shù)據(jù)。

#實(shí)現(xiàn)代碼如下

<?php$fp = fopen($file, "r");$num = 10;$chunk = 4096;$fs = sprintf("%u", filesize($file));$max = (intval($fs) == PHP_INT_MAX) ? PHP_INT_MAX : filesize($file);for ($len = 0; $len < $max; $len += $chunk){ $seekSize = ($max - $len > $chunk) ? $chunk : $max - $len; fseek($fp, ($len + $seekSize) * -1, SEEK_END); $readData = fread($fp, $seekSize) . $readData; if (substr_count($readData, "/n") >= $num + 1) { preg_match("!(.*?/n){" . ($num) . "}$!", $readData, $match); $data = $match[0]; break; }}fclose($fp);echo $data;?>

整個代碼執(zhí)行完成耗時 0.0009(s)。

方法三

<?phpfunction tail($fp, $n, $base = 5){ assert($n > 0); $pos = $n + 1; $lines = array(); while (count($lines) <= $n) { try { fseek($fp, -$pos, SEEK_END); } catch (Exception $e) { fseek(0); break; } $pos *= $base; while (!feof($fp)) { array_unshift($lines, fgets($fp)); } } return array_slice($lines, 0, $n);}var_dump(tail(fopen("access.log", "r+"), 10));?>

整個代碼執(zhí)行完成耗時 0.0003(s)

 

 

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 平安县| 蒙山县| 万山特区| 清水县| 嘉善县| 静安区| 沁水县| 乃东县| 台安县| 全州县| 清徐县| 台东县| 平山县| 扬中市| 通许县| 抚州市| 西华县| 德格县| 沂南县| 灵石县| 恩施市| 麻阳| 谷城县| 武平县| 双桥区| 民和| 奉新县| 沙雅县| 高阳县| 西华县| 涞源县| 古浪县| 东乡县| 勃利县| 长宁区| 博湖县| 太和县| 石阡县| 台东市| 定兴县| 桃园市|