当前位置:首页 > 网站建设

【北京网站制作】PHP并发下安全读写文件函数

做一个网站需要多少钱2019-01-27975人围观

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

  下面的这个函数是从大名鼎鼎的可道云的代码中找到的。可道云相信大家都不会陌生,它是一个无数据库的程序,因此配置存储全都是靠这个函数完成的,所以这段代码的安全性和普适性绝对毋庸置疑,可以放心的用于项目中(注意尽量保留原作者的版权信息就行了)。
  代码的原版位于可道云的 /app/function/file.function.php 第 729 行左右。原版代码的逻辑是 写文件时如果原文件不存在,则直接返回 false,我把这一部分稍微修改了一下,改成了 如果目标文件不存在,则创建文件并写入。

  不多说了,全部的代码如下:


<?php
 
/**
 * @link http://kodcloud.com/
 * @author warlee | e-mail:[email protected]
 * @copyright warlee 2014.(Shanghai)Co.,Ltd
 * @license http://kodcloud.com/tools/license/license.txt
 */
 
 
/**
 * 安全读取文件,避免并发下读取数据为空
 * 
 * @param $file 要读取的文件路径
 * @param $timeout 读取超时时间 
 * @return 读取到的文件内容 | false - 读取失败
 */
function file_read_safe($file, $timeout = 5) {
    if (!$file || !file_exists($file)) return false;
    $fp = @fopen($file, 'r');
    if (!$fp) return false;
    $startTime = microtime(true);
    
    // 在指定时间内完成对文件的独占锁定
    do {
        $locked = flock($fp, LOCK_EX | LOCK_NB);
        if (!$locked) {
            usleep(mt_rand(1, 50) * 1000);     // 随机等待1~50ms再试
        }
    }
    while ((!$locked) && ((microtime(true) - $startTime) < $timeout));
    
    if ($locked && filesize($file) >= 0) {
        $result = @fread($fp, filesize($file));
        flock($fp, LOCK_UN);
        fclose($fp);
        if (filesize($file) == 0) {
            return '';
        }
        return $result;
    } else {
        flock($fp, LOCK_UN);
        fclose($fp);
        return false;
    }
}
 
/**
 * 安全写文件,避免并发下写入数据为空
 * 
 * @param $file 要写入的文件路径
 * @param $buffer 要写入的文件二进制流(文件内容)
 * @param $timeout 写入超时时间 
 * @return 写入的字符数 | false - 写入失败
 */
function file_wirte_safe($file, $buffer, $timeout = 5) {
    clearstatcache();
    if (strlen($file) == 0 || !$file) return false;
    
    // 文件不存在则创建
    if (!file_exists($file)) {
        @file_put_contents($file, '');
    }
    if(!is_writeable($file)) return false;    // 不可写
    
    // 在指定时间内完成对文件的独占锁定
    $fp = fopen($file, 'r+');
    $startTime = microtime(true);
    do {
        $locked = flock($fp, LOCK_EX); 
        if (!$locked) {
            usleep(mt_rand(1, 50) * 1000);   // 随机等待1~50ms再试
        }
    }
    while ((!$locked) && ((microtime(true) - $startTime) < $timeout));    
    
    if ($locked) {
        $tempFile = $file.'.temp';
        $result = file_put_contents($tempFile, $buffer, LOCK_EX);
        
        if (!$result || !file_exists($tempFile)) {
            flock($fp, LOCK_UN);
            fclose($fp);
            return false;
        }
        @unlink($tempFile);
        
        ftruncate($fp, 0);
        rewind($fp);
        $result = fwrite($fp, $buffer);
        flock($fp, LOCK_UN);
        fclose($fp);
        clearstatcache();
        return $result;
    } else {
        flock($fp, LOCK_UN);
        fclose($fp);
        return false;
    }
}

作者mengkun

林记seo博客和你一起学习SEO知识,共同分享SEO优化,网站建设,网络营销,网络推广经验,本博客主要提供,网站优化,网络推广,网站建设,网络营销,网站推广,等相关信息

 

    版权声明:

    博主在此发文(包括但不限于汉字、拼音、拉丁字母)均为随意敲击键盘所出,用于检验本人电脑键盘录入、屏幕显示的机械、光电性能,并不代表本人局部或全部同意、支持或者反对观点

    如需要详查请直接与键盘生产厂商法人代表联系。挖井挑水无水表,不会网购无快递。

    文章内容除非注明原创,否则来源于互联网,不代表本人的任何立场;涉及到的软件来源于互联网,仅供个人下载使用,请勿用于商业用途,版权归软件开发者所有,下载后请于24小时内删除,请支持正版!

    因下载本站任何资源造成的损失,全部责任由使用者本人承担!

    如果你是版权方,认为本文内容对您的权益有所侵犯,请联系博主,待博主进行严格地审查和背景调查后,情况属实的将在三天内将本文删除或修正。

    博主的文章没有高度、深度和广度,只是凑字数。由于博主的水平不高(其实是个菜B),不足和错误之处在所难免,希望大家能够批评指出。