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

首頁(yè) > 開(kāi)發(fā) > PHP > 正文

PHP 讀取大文件程序代碼

2024-05-04 21:47:59
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

一般讀取文件我們用fopen 或者 file_get_contents,前者可以循環(huán)讀取,后者可以一次性讀取,但都是將文件內(nèi)容一次性加載來(lái)操作,如果加載的文件特別大時(shí),如幾百M(fèi),上G時(shí),這時(shí)性能就降下來(lái)了,那么PHP里有沒(méi)有對(duì)大文件的處理函數(shù)或者類呢? 答案是有的

PHP真的越來(lái)越“面向?qū)ο?rdquo;了,一些原有的基礎(chǔ)的SPL方法都開(kāi)始陸續(xù)地實(shí)現(xiàn)出class了.

從 PHP 5.1.0 開(kāi)始,SPL 庫(kù)增加了 SplFileObject 與 SplFileInfo 兩個(gè)標(biāo)準(zhǔn)的文件操作類,SplFileInfo 是從 PHP 5.1.2 開(kāi)始實(shí)現(xiàn)的,從字面意思理解看,可以看出 SplFileObject 要比 SplFileInfo 更為強(qiáng)大.

不錯(cuò),SplFileInfo 僅用于獲取文件的一些屬性信息,如文件大小、文件訪問(wèn)時(shí)間、文件修改時(shí)間、后綴名等值,而 SplFileObject 是繼承 SplFileInfo 這些功能的.

代碼如下:

  1.  /** 返回文件從X行到Y(jié)行的內(nèi)容(支持php5、php4)   
  2.  * @param string $filename 文件名 
  3.  * @param int $startLine 開(kāi)始的行數(shù) 
  4.  * @param int $endLine 結(jié)束的行數(shù) 
  5.  * @return string 
  6.  */ 
  7. function getFileLines($filename$startLine = 1, $endLine=50, $method='rb') { 
  8.     $content = array(); 
  9.     $count = $endLine - $startLine;   
  10.     // 判斷php版本(因?yàn)橐玫絊plFileObject,PHP>=5.1.0) 
  11.     if(version_compare(PHP_VERSION, '5.1.0''>=')){ 
  12.         $fp = new SplFileObject($filename$method); 
  13.         $fp->seek($startLine-1);// 轉(zhuǎn)到第N行, seek方法參數(shù)從0開(kāi)始計(jì)數(shù) 
  14.         for($i = 0; $i <= $count; ++$i) { 
  15.             $content[]=$fp->current();// current()獲取當(dāng)前行內(nèi)容 
  16.             $fp->next();// 下一行 
  17.         } 
  18.     }else{//PHP<5.1 
  19.         $fp = fopen($filename$method); 
  20.         if(!$fpreturn 'error:can not read file'
  21.         for ($i=1;$i<$startLine;++$i) {// 跳過(guò)前$startLine行 
  22.             fgets($fp); 
  23.         } 
  24.         for($i;$i<=$endLine;++$i){ 
  25.             $content[]=fgets($fp);// 讀取文件行內(nèi)容 
  26.         } 
  27.         fclose($fp); 
  28.     } 
  29.     return array_filter($content); // array_filter過(guò)濾:false,null,'' 

上面都沒(méi)加”讀取到末尾的判斷”:!$fp->eof() 或者 !feof($fp),加上這個(gè)判斷影響效率,自己加上測(cè)試很多很多很多行的運(yùn)行時(shí)間就曉得了,而且這里加上也完全沒(méi)必要.

從上面的函數(shù)就可以看出來(lái)使用SplFileObject比下面的fgets要快多了,特別是文件行數(shù)非常多、并且要取后面的內(nèi)容的時(shí)候,fgets要兩個(gè)循環(huán)才可以,并且要循環(huán)$endLine次.

此方法花了不少功夫,測(cè)試了很多中寫法,就是想得出效率最高的方法,哪位覺(jué)得有值得改進(jìn)的歡迎賜教.

使用,返回35270行-35280行的內(nèi)容,代碼如下:

  1. echo '<pre>'
  2. var_dump(getFileLines('test.php',35270,35280)); 
  3. echo '</pre>'

再看一個(gè)實(shí)例,代碼如下:

  1. function readBigFile($filename$count = 20, $tag = "rn") {  
  2. $content = "";//最終內(nèi)容  
  3. $current = "";//當(dāng)前讀取內(nèi)容寄存  
  4. $step= 1;//每次走多少字符  
  5. $tagLen = strlen($tag);  
  6. $start = 0;//起始位置  
  7. $i = 0;//計(jì)數(shù)器  
  8. $handle = fopen($filename,'r+');//讀寫模式打開(kāi)文件,指針指向文件起始位置  
  9. while($i < $count && !feof($handle)) {  
  10. fseek($handle$start, SEEK_SET);//指針設(shè)置在文件開(kāi)頭  
  11. $current = fread($handle,$step);//讀取文件  
  12. $content .= $current;//組合字符串  
  13. $start += $step;//依據(jù)步長(zhǎng)向前移動(dòng)  
  14. //依據(jù)分隔符的長(zhǎng)度截取字符串最后免得幾個(gè)字符  
  15. $substrTag = substr($content, -$tagLen);  
  16. if ($substrTag == $tag) { //判斷是否為判斷是否是換行或其他分隔符  
  17. $i++;  
  18. $content .= "<br />";  
  19. }  
  20. }  
  21. //關(guān)閉文件  
  22. fclose($handle);  
  23. //返回結(jié)果  
  24. return $content;  
  25. }  
  26. $filename = "csdn.sql";//需要讀取的文件  
  27. $tag = "n";//行分隔符 注意這里必須用雙引號(hào)  
  28. $count = 100;//讀取行數(shù)  
  29. $data = readBigFile($filename,$count,$tag);  
  30. echo $data

注意:通過(guò)使用PHP的fseek和fread相結(jié)合,即可做到隨意讀取文件中的某一部份數(shù)據(jù),關(guān)于函數(shù)傳入的變量$tag的值,根據(jù)系統(tǒng)不一樣,傳入的值也是有區(qū)別的:Windows用”rn”,linux/unix用”n”,Mac OS用”r”.

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 芷江| 商河县| 灌南县| 吉安市| 通山县| 竹溪县| 磴口县| 平泉县| 禄丰县| 宝应县| 广南县| 蛟河市| 平江县| 化隆| 出国| 永吉县| 宣武区| 太白县| 龙门县| 卢氏县| 普兰县| 江陵县| 玉树县| 合山市| 富锦市| 崇信县| 南丹县| 志丹县| 通化县| 沂水县| 城固县| 肥乡县| 安新县| 玉林市| 高要市| 甘南县| 荥阳市| 广平县| 南京市| 陕西省| 舒兰市|