Php 福彭、弗瑞德和弗洛克
我需要锁定文件,读取数据,写入文件,然后关闭它。我遇到的问题是,我正在尝试为fopen找到正确的模式 使用“a+”-始终附加数据,“w+”在打开时截断所有数据,使用“x+”-无法锁定文件 这是我的代码: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 .=
$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开始提供