0

我有一个脚本可以计算单词的频率并将结果保存到 json 文件中。再次运行时,它会读取现有的 json 文件,组合结果,然后重新写入 json 文件。这可以在一个请求中重复发生,并且可以有许多同时请求,所以我曾经flock()尝试防止错误。我昨天让它运行了一段时间并获得了良好的数据,但今天早上我检查了文件已损坏。(仍然是一个很好的文本文件,但 json 被破坏了。)

以下是我的代码的相关部分:

if(is_file('/home/myuser/public_html/word_counts.json'))
  {
    $prevoius_counts=json_decode(file_get_contents('/home/myuser/public_html/word_counts.json'),true);
  }
if(!$prevoius_counts)  
  {
    $prevoius_counts=array();
  } 
$new_counts=count_words($item->Description,$item->IDENTIFIER); //Creates an array like: array('the'=>20,'it'=>15,'spectacular'=>1);
$combined_counts=sum_associatve(array($new_counts,$prevoius_counts)); like array_merge, but sums duplicate keys instead of overwriting.

$fh=fopen('/home/myuser/public_html/word_counts.json','c'); //this will always be over-written with new data, but the "c" prevents it from being truncated to 0 bytes
if (flock($fh, LOCK_EX)) 
  {
    fwrite($fh, json_encode($combined_counts));
    flock($fh, LOCK_UN);    // release the lock
  }
fclose($fh);

function count_words($description,$unique=null){
// /([\s_;?!\/\(\)\[\]{}<>\r\n"]|\.$|(?<=\D)[:,.\-]|[:,.\-](?=\D))/
// /([\s\-_,:;?!\/\(\)\[\]{}<>\r\n"]|(?<!\d)\.(?!\d))/
// http://rick.measham.id.au/paste/explain.pl?regex=
// http://stackoverflow.com/questions/20006448
    $to_be_counted=strtolower($description);
    $to_be_counted.=' BLOCKS '.$unique;
    $words=preg_split('/([\s_;?!\/\(\)\[\]{}<>\r\n"]|\.$|(?<=\D)[:,.]|[:,.](?=\D))/', $to_be_counted, null, PREG_SPLIT_NO_EMPTY);
    return array_count_values ($words);
  }

  function sum_associatve($arrays){
    $sum = array();
    foreach ($arrays as $array) {
        foreach ($array as $key => $value) {
            if (isset($sum[$key])) {
                $sum[$key] += $value;
            } else {
                $sum[$key] = $value;
            }
        }
    } 
    return $sum;
}

由于它工作了一段时间但最终写入了错误的 json,我不知道这是否是文件锁定问题,或者我是否遇到了 json_encode 返回错误数据的问题......?

4

1 回答 1

0

这似乎有效,但我仍然不能 100% 确定它会得到一切:

if (flock($fh, LOCK_EX)) 
  {
    ftruncate($fh, 0);
    fwrite($fh, json_encode($combined_counts));
    flock($fh, LOCK_UN);    // release the lock
  }
fclose($fh);
于 2013-11-26T15:13:19.183 回答