日韩天天综合网_野战两个奶头被亲到高潮_亚洲日韩欧美精品综合_av女人天堂污污污_视频一区**字幕无弹窗_国产亚洲欧美小视频_国内性爱精品在线免费视频_国产一级电影在线播放_日韩欧美内地福利_亚洲一二三不卡片区

php讀取操作大文件,超出內(nèi)存大小,三種方法_PHP教程

編輯Tag賺U幣
教程Tag:暫無(wú)Tag,歡迎添加,賺取U幣!

推薦:php數(shù)組排序
A.內(nèi)部排序(直接加載到內(nèi)存進(jìn)行排序):包括交換式排序(冒泡和快速法)、選擇式排序、插入式排序 B.外部排序(因數(shù)據(jù)量大,需借助外部存儲(chǔ)進(jìn)行排序):包括合并排序、直接合并排序 【冒泡排序:從后向前,依次比較相鄰元素的排序碼,若發(fā)現(xiàn)逆序則交換,一輪結(jié)束后,再

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

需求

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

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

1.2B行為,簡(jiǎn)單粗暴,簡(jiǎn)單直接采用file函數(shù)來(lái)操作

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

下面是一段用file來(lái)取出這具文件最后一行的代碼.

  1. ini_set('memory_limit','-1'); 
  2. $file = 'access.log'
  3. $data = file($file); 
  4. $line = $data[count($data)-1]; 
  5. echo $line
整個(gè)代碼執(zhí)行完成耗時(shí) 116.9613 (s).
我機(jī)器是2個(gè)G的內(nèi)存,當(dāng)按下F5運(yùn)行時(shí),系統(tǒng)直接變灰,差不多20分鐘后才恢復(fù)過(guò)來(lái),可見(jiàn)將這么大的文件全部直接讀入內(nèi)存,后果是多少?lài)?yán)重,所以不在萬(wàn) 不得以,memory_limit這東西不能調(diào)得太高,否則只有打電話(huà)給機(jī)房,讓reset機(jī)器了.
 
2.直接調(diào)用linux的tail命令來(lái)顯示最 后幾行
 
在linux命令行下,可以直接使用tail -n 10 access.log很輕易的顯示日志文件最后幾行,可以直接用php來(lái)調(diào)用tail命令,執(zhí)行php代碼如下.
  1. file = 'access.log'
  2. $file = escapeshellarg($file); // 對(duì)命令行參數(shù)進(jìn)行安全轉(zhuǎn)義 
  3. $line = `tail -n 1 $file`; 
  4. echo $/php] 
  5. 整個(gè)代碼執(zhí)行完成耗時(shí) 0.0034 (s) 
  6.   
  7. 3. 直接使用php的fseek來(lái)進(jìn)行文件操作 
  8.   
  9. 這種方式是最為普遍的方式,它不需要將文件的內(nèi)容全部讀入內(nèi)容,而是直接通過(guò)指針來(lái)操作,所以效率是相當(dāng)高效的.在使用fseek來(lái)對(duì)文件進(jìn)行操作 時(shí),也有多種不同的方法,效率可能也是略有差別的,下面是常用的兩種方法. 
  10. 方法一 
  11. 首先通過(guò)fseek找到文件的最后一位EOF,然后找最后一行的起始位置,取這一行的數(shù)據(jù),再找次一行的起始位置, 再取這一行的位置,依次類(lèi)推,直到找到了$num行。 
  12. 實(shí)現(xiàn)代碼如下 
  13.   
  14. $fp = fopen($file"r"); 
  15. $line = 10; 
  16. $pos = -2; 
  17. $t = " "
  18. $data = ""
  19. while ($line > 0) { 
  20.     while ($t != "\n") { 
  21.         fseek($fp$pos, SEEK_END); 
  22.         $t = fgetc($fp); 
  23.         $pos --; 
  24.     } 
  25.     $t = " "
  26.     $data .= fgets($fp); 
  27.     $line --; 
  28. fclose ($fp); 
  29. echo $data 
整個(gè)代碼執(zhí)行完成耗時(shí) 0.0095 (s)
 
方法二
還是采用fseek的方式從文件最后開(kāi)始讀,但這時(shí)不是一位一位的讀,而是一塊一塊的讀,每讀一塊數(shù)據(jù)時(shí),就將讀取后的數(shù)據(jù)放在一個(gè)buf里,然后通過(guò)換 行符(\n)的個(gè)數(shù)來(lái)判斷是否已經(jīng)讀完最后$num行數(shù)據(jù).
實(shí)現(xiàn)代碼如下
  1. $fp = fopen($file"r"); 
  2. $num = 10; 
  3. $chunk = 4096; 
  4. $fs = sprintf("%u"filesize($file)); 
  5. $max = (intval($fs) == PHP_INT_MAX) ? PHP_INT_MAX : filesize($file); 
  6. for ($len = 0; $len < $max$len += $chunk) { 
  7.     $seekSize = ($max - $len &gt; $chunk) ? $chunk : $max - $len
  8.     fseek($fp, ($len + $seekSize) * -1, SEEK_END); 
  9.     $readData = fread($fp$seekSize) . $readData
  10.   
  11.     if (substr_count($readData"\n") &gt;= $num + 1) { 
  12.         preg_match("!(.*?\n){".($num)."}$!"$readData$match); 
  13.         $data = $match[0]; 
  14.         break
  15.     } 
  16. fclose($fp); 
  17. echo $data
整個(gè)代碼執(zhí)行完成耗時(shí) 0.0009(s).
 
方法三
  1. function tail($fp,$n,$base=5) 
  2.     assert($n>0); 
  3.     $pos = $n+1; 
  4.     $lines = array(); 
  5.     while(count($lines)< =$n){ 
  6.         try{ 
  7.             fseek($fp,-$pos,SEEK_END); 
  8.         } catch (Exception $e){ 
  9.             fseek(0); 
  10.             break
  11.         } 
  12.         $pos *= $base
  13.         while(!feof($fp)){ 
  14.             array_unshift($lines,fgets($fp)); 
  15.         } 
  16.     } 
  17.     return array_slice($lines,0,$n); 
  18. var_dump(tail(fopen("access.log","r+"),10)); 
整個(gè)代碼執(zhí)行完成耗時(shí) 0.0003(s)
轉(zhuǎn)自:塵緣博客, http://www.4wei.cn/archives/1001748

分享:php插入中文到sql server 2008里出現(xiàn)亂碼的解決辦法
今天使用php操作數(shù)據(jù)庫(kù)時(shí)發(fā)現(xiàn)插入SQL Server 2008數(shù)據(jù)庫(kù)里的中文字段出現(xiàn)亂碼,下面是我一開(kāi)始時(shí)的一些情況: 開(kāi)發(fā)環(huán)境是php5.3.3+Apache2.2.17+SQL Server 2008,php腳本文件的編碼是 utf-8 ,傳給數(shù)據(jù)庫(kù)的編碼是 GB2312 (SQL Server的默認(rèn)字符編碼可能是這個(gè),我不

來(lái)源:塵緣//所屬分類(lèi):PHP教程/更新時(shí)間:2012-07-21
相關(guān)PHP教程