Fopen, Fread и Flock - PullRequest
       8

Fopen, Fread и Flock

4 голосов
/ 16 апреля 2011

Мне нужно заблокировать файл, прочитать данные, записать в файл и затем закрыть его.Проблема в том, что я пытаюсь найти правильный режим для 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);

Ответы [ 3 ]

7 голосов
/ 16 апреля 2011

Вы хотите '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);
        }
2 голосов
/ 16 апреля 2011

Я верю, что вы хотите c+.Это похоже на r+ за исключением того, что оно создаст файл, который не существует.Если вы не хотите этого делать, используйте вместо этого r+.Открыв файл, используйте flock() по мере необходимости.Вы можете c+ открыть для чтения и записи, а также.Кроме этого, я думаю, что вы можете использовать тот же код.

Другой ответ правильный, но они используют дополнительный шаг, чтобы определить, использовать ли r или w, когда c сделает это автоматически.

0 голосов
/ 16 апреля 2011

Код Фрэнка Фармера не лучше, чем твой.Между file_exists и fopen другой процесс может выполнять свои собственные манипуляции с файлом.

Создать файл семафора перед открытием файла 'task'.
Что-то вроде:

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