众所周知,在高并发的状态下,直接使用 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. }  
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系贝贝进行处理。
本站默认解压密码:www.hibbba.com