【问题标题】:PHP lock text file for editing?PHP锁定文本文件进行编辑?
【发布时间】:2013-03-04 08:34:25
【问题描述】:

我有一个将其输入写入文本文件的表单。 是否可以锁定文本文件以进行编辑,并可能给出友好消息“文件已被其他用户编辑,请稍后再试”。

如果文件同时有多个编辑器,我想避免冲突。

这是当前添加条目的方式。

$content = file_get_contents("./file.csv");
$fh = fopen("./file.csv", "w");
fwrite($fh, $date_yy . '-' . $date_mm . '-' . $date_dd . '|' . $address . '|' . $person . '|' . $time_hh . ':' . $time_mm) ;
fwrite($fh, "\n" . $content);
fclose($fh);

有什么想法吗?

【问题讨论】:

标签: php file-locking


【解决方案1】:

您可以使用flock() 函数来锁定文件。更多内容见this

类似:

   <?php

      $content = file_get_contents("./file.csv");
      $fp = fopen("./file.csv", "w"); // open it for WRITING ("w")
      if (flock($fp, LOCK_EX)) 
      {
      // do your file writes here
      fwrite($fh, $date_yy . '-' . $date_mm . '-' . $date_dd . '|' . $address . '|' .  $person . '|' . $time_hh . ':' . $time_mm);
      fwrite($fh, "\n" . $content);
      fclose($fh);
      flock($fh, LOCK_UN); // unlock the file
      } 
   ?> 

【讨论】:

  • fopenflock 之间,文件将被清零(由于w 访问),希望这是 OP 想要的...此外,解锁应该在文件关闭之前...
  • 目标是在文件中添加新行,而不是重置或替换内容。
  • @Janne 所以你最好使用a 访问,而不是w
  • @ring0, "解锁应该在文件关闭之前",对,但是解锁也可以完全省略,因为当文件关闭时,锁被释放。
【解决方案2】:

按要求排序:

  1. 使用数据库。
  2. 使用多个文本文件。
  3. 使用locks:

例如:

$lockwait = 2;       // seconds to wait for lock
$waittime = 250000;  // microseconds to wait between lock attempts
// 2s / 250000us = 8 attempts.
$myfile = '/path/to/file.txt';

if( $fh = fopen($myfile, 'a') ) {
  $waitsum = 0;
  // attempt to get exclusive, non-blocking lock
  $locked = flock($fh, LOCK_EX | LOCK_NB); 
  while( !$locked && ($waitsum <= $lockwait) ) {
    $waitsum += $waittime/1000000; // microseconds to seconds
    usleep($waittime);
    $locked = flock($fh, LOCK_EX | LOCK_NB);
  }
  if( !$locked ) {
    echo "Could not lock $myfile for write within $lockwait seconds.";
  } else {
    // write out your data here
    flock($fh, LOCK_UN);  // ALWAYS unlock
  }
  fclose($fh);            // ALWAYS close your file handle
} else {
  echo "Could not open $myfile";
  exit 1;
}

【讨论】:

    【解决方案3】:

    您可以使用PHP's flock function 锁定文件以进行写入,但该锁定不会在 Web 请求中持续存在,并且不适用于 NFS 挂载(至少根据我的经验)。

    你最好在同一目录下创建一个令牌文件,检查它是否存在,如果存在则报告错误。

    与任何锁定方案一样,您将在操作完成后保留竞争条件和锁定,因此您需要一种方法来缓解这些问题。

    我建议在编辑该值并将其存储在锁定文件中之前创建文件的哈希值。还将该哈希作为编辑表单的一部分发送给客户端(因此它作为提交请求中的数据返回)。在写入之前,将传递的哈希值与文件中的值进行比较。如果它们相同,则提交数据并解除锁定。

    如果它们不同,则显示错误。

    【讨论】:

    • 为什么锁不会在 Web 请求中持续存在?锁在文件上,而不是描述符上(至少在 Linux 上)
    • 我读到 fclose 删除了锁,所以你的锁将在文件句柄打开的持续时间内。我在植绒方面运气不佳,所以我倾向于避免它。我认为在这种情况下使用信号量文件是一个更好的解决方案,因为应该在编辑开始时获得锁定并在完成后释放,这可能是几个提交/验证/重新提交周期之后。我不是想回避你的问题,我只是没有一个好的答案。
    • 不,flock c 函数(php 的flock 实现)对描述符进行操作。 linux.die.net/man/2/flock
    【解决方案4】:

    你可以试试flock — Portable advisory file locking

    http://php.net/manual/en/function.flock.php

    【讨论】:

      【解决方案5】:

      我只会使用一个简单的整数或类似的东西。

        $content = file_get_contents("./file.csv");
        $fh = fopen("./file.csv", "w");
        $status = 1;
      
      ...      
      
      if($status == 1){
         fwrite($fh, $date_yy . '-' . $date_mm . '-' . $date_dd . '|' . $address . '|' . $person . '|' . $time_hh . ':' . $time_mm);
         fwrite($fh, "\n" . $content);
         fclose($fh);
         $status = 0;
        }
      else
           echo "the file is edited by another user, please try again later.";
      

      你是这个意思吗?

      【讨论】:

      • $status = 1; if ($status == 1) { 我希望我能理解那个算法
      • @ring0 大声笑我知道完全按照我所说的那样做是不可行的。也许更早或者有一个 checkStatus() 函数。某个地方只是跟踪用户是否单击了编辑,并在提交时重置回 0。我意识到以上在技术上是不正确的。道歉
      猜你喜欢
      • 2016-11-04
      • 2019-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多