PHP并发下安全读写文件函数[php源码]

(゜-゜)つロ 干杯~

众所周知,在高并发的状态下,直接使用 PHP 读写同一个文件时,可能会导致文件内容丢失,于是乎就需要额外的代码来解决这个问题。大致的思路是先使用 flock 函数对原文件进行锁死,再来读写。

  1. <?php  
  2.    
  3.   
  4.    
  5. /** 
  6.  * 安全读取文件,避免并发下读取数据为空 
  7.  *  
  8.  * @param $file 要读取的文件路径 
  9.  * @param $timeout 读取超时时间  
  10.  * @return 读取到的文件内容 | false - 读取失败 
  11.  */  
  12. function file_read_safe($file$timeout = 5) {  
  13.     if (!$file || !file_exists($file)) return false;  
  14.     $fp = @fopen($file, 'r');  
  15.     if (!$fpreturn false;  
  16.     $startTime = microtime(true);  
  17.       
  18.     // 在指定时间内完成对文件的独占锁定  
  19.     do {  
  20.         $locked = flock($fp, LOCK_EX | LOCK_NB);  
  21.         if (!$locked) {  
  22.             usleep(mt_rand(1, 50) * 1000);     // 随机等待1~50ms再试  
  23.         }  
  24.     }  
  25.     while ((!$locked) && ((microtime(true) - $startTime) < $timeout));  
  26.       
  27.     if ($locked && filesize($file) >= 0) {  
  28.         $result = @fread($fpfilesize($file));  
  29.         flock($fp, LOCK_UN);  
  30.         fclose($fp);  
  31.         if (filesize($file) == 0) {  
  32.             return '';  
  33.         }  
  34.         return $result;  
  35.     } else {  
  36.         flock($fp, LOCK_UN);  
  37.         fclose($fp);  
  38.         return false;  
  39.     }  
  40. }  
  41.    
  42. /** 
  43.  * 安全写文件,避免并发下写入数据为空 
  44.  *  
  45.  * @param $file 要写入的文件路径 
  46.  * @param $buffer 要写入的文件二进制流(文件内容) 
  47.  * @param $timeout 写入超时时间  
  48.  * @return 写入的字符数 | false - 写入失败 
  49.  */  
  50. function file_write_safe($file$buffer$timeout = 5) {  
  51.     clearstatcache();  
  52.     if (strlen($file) == 0 || !$filereturn false;  
  53.       
  54.     // 文件不存在则创建  
  55.     if (!file_exists($file)) {  
  56.         @file_put_contents($file'');  
  57.     }  
  58.     if(!is_writeable($file)) return false;    // 不可写  
  59.       
  60.     // 在指定时间内完成对文件的独占锁定  
  61.     $fp = fopen($file, 'r+');  
  62.     $startTime = microtime(true);  
  63.     do {  
  64.         $locked = flock($fp, LOCK_EX);   
  65.         if (!$locked) {  
  66.             usleep(mt_rand(1, 50) * 1000);   // 随机等待1~50ms再试  
  67.         }  
  68.     }  
  69.     while ((!$locked) && ((microtime(true) - $startTime) < $timeout));      
  70.       
  71.     if ($locked) {  
  72.         $tempFile = $file.'.temp';  
  73.         $result = file_put_contents($tempFile$buffer, LOCK_EX);  
  74.           
  75.         if (!$result || !file_exists($tempFile)) {  
  76.             flock($fp, LOCK_UN);  
  77.             fclose($fp);  
  78.             return false;  
  79.         }  
  80.         @unlink($tempFile);  
  81.           
  82.         ftruncate($fp, 0);  
  83.         rewind($fp);  
  84.         $result = fwrite($fp$buffer);  
  85.         flock($fp, LOCK_UN);  
  86.         fclose($fp);  
  87.         clearstatcache();  
  88.         return $result;  
  89.     } else {  
  90.         flock($fp, LOCK_UN);  
  91.         fclose($fp);  
  92.         return false;  
  93.     }  
  94. }  
   

如果资源下载失效请到 留言板 留言或者 QQ 联系我。

本站默认解压密码:www.hibbba.com

(゜-゜)つロ 干杯~

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: