Php 福彭、弗瑞德和弗洛克

Php 福彭、弗瑞德和弗洛克,php,file,fopen,Php,File,Fopen,我需要锁定文件,读取数据,写入文件,然后关闭它。我遇到的问题是,我正在尝试为fopen找到正确的模式 使用“a+”-始终附加数据,“w+”在打开时截断所有数据,使用“x+”-无法锁定文件 这是我的代码: $fh_task = fopen($task_file, 'w+'); flock($fh_task, LOCK_EX) or die('Cant lock '.$task_file); $opt_line = ''; while(!feof($fh_task)){ $opt_line .=

我需要锁定文件,读取数据,写入文件,然后关闭它。我遇到的问题是,我正在尝试为fopen找到正确的模式

使用“a+”-始终附加数据,“w+”在打开时截断所有数据,使用“x+”-无法锁定文件

这是我的代码:

$fh_task = fopen($task_file, 'w+');
flock($fh_task, LOCK_EX) or die('Cant lock '.$task_file);
$opt_line = '';
while(!feof($fh_task)){
  $opt_line .= fread($fh_task, 4096);
}
$options = unserialize($opt_line);
$options['procceed']++;
rewind($fh_task);
fwrite($fh_task, serialize($options));
flock($fh_task, LOCK_UN);
fclose($fh_task);

您需要
'r+'
(或者
c+
,如果您使用的是较新版本的PHP)
r+
不会截断(c+也不会截断),但仍然允许您编写

下面是我上次使用这些函数时的摘录:

        /* 
          if file exists, open in read+ plus mode so we can try to lock it 
          -- opening in w+ would truncate the file *before* we could get a lock!
        */

        if(version_compare(PHP_VERSION, '5.2.6') >= 0) {
            $mode = 'c+';
        } else {
            //'c+' would be the ideal $mode to use, but that's only 
            //available in PHP >=5.2.6

            $mode = file_exists($file) ? 'r+' : 'w+';
            //there's a small chance of a race condition here
            // -- two processes could end up opening the file with 'w+'
        }

        //open file
        if($handle = @fopen($file, $mode)) {
            //get write lock
            flock($handle,LOCK_EX);
            //write data
            fwrite($handle, $myData);
            //truncate all data in file following the data we just wrote 
            ftruncate($handle,ftell($handle));
            //release write lock -- fclose does this automatically
            //but only in PHP <= 5.3.2
            flock($handle,LOCK_UN);
            //close file
            fclose($handle);
        }
/*
如果文件存在,请以读+加模式打开,以便我们可以尝试锁定它
--在w+中打开会在我们获得锁之前截断文件*!
*/
如果(版本比较(PHP版本,'5.2.6')>=0){
$mode='c+';
}否则{
//“c+”将是使用的理想$mode,但这只是
//可用PHP>=5.2.6
$mode=file_存在($file)?'r+':'w+';
//这里有一个小机会的比赛条件
//--两个进程可能以“w+”打开文件结束
}
//打开文件
如果($handle=@fopen($file$mode)){
//获取写锁
植绒($手柄,锁紧装置);
//写入数据
fwrite($handle,$myData);
//截断文件中的所有数据,这些数据跟在我们刚刚编写的数据后面
ftruncate($handle,ftell($handle));
//释放写锁——fclose会自动执行此操作

//但仅在PHP中我相信您需要
c+
。这与
r+
类似,只是它会创建一个不存在的文件。如果您不想这样做,请使用
r+
。打开文件后,使用
flock()
根据需要。您可以
c+
打开进行读写。除此之外,我认为您可以使用相同的代码


另一个答案是正确的,但他们正在使用一个额外的步骤来确定当c将自动执行此操作时使用r或w。

Frank Farmer的代码并不比您的更好。在文件和fopen之间,其他进程可以对文件进行自己的操作

在打开“任务”文件之前创建信号量文件。
比如:

if (($f_sem = @fopen($task_file.'.sem', 'x')))
{
    //your code (with flock)
    fclose($f_sem);
    unlink($task_file.'.sem');
}

alexy13,谢谢你的编辑,我的英语很差-我认为这不是个好主意。任务文件这是线程下的通信方式。当我使用简单锁时,每个线程都会等待文件锁解除。对于信号量文件,我只会得到false来创建它,其他什么都没有。如果你真的想创建,请等待解锁(这种方法可能很危险),而不是将flock应用于信号量文件,这很容易-在我的代码中,在“您的代码”之前写flock。
flock($handle,LOCK\u UN)
是不需要的,因为
fclose($handle)
无论如何都会这样做-至少perl文档的状态是这样。看起来这在PHP中最近可能发生了变化。
在5.3.2之前的PHP版本上,锁也由fclose()释放(脚本完成时也会自动调用)。
关闭文件资源句柄时的自动解锁已被删除[在5.3.2中]。现在必须手动解锁。
+1.编辑了我的答案,加入了
c+
,因为这绝对是问题的正确解决方案。编辑:噢。
c+
仅从5.2.6开始提供