Целое число усекается при записи в текстовый файл на PHP? - PullRequest
2 голосов
/ 01 ноября 2010

Я написал счетчик загрузок:

$hit_count = @file_get_contents('download.txt');
$hit_count++;
@file_put_contents('download.txt', $hit_count);

header('Location: file/xxx.zip');

Так просто. Проблема в том, что номер статистики усекается до 4 цифр, поэтому реальный счет не отображается:

http://www.converthub.com/batch-image-converter/download.txt

Программа конвертирования пакетных изображений загружается пару сотен раз в день, а счетчик PHP работает уже несколько месяцев. Первый раз, когда я узнал об этом, было около 2 месяцев назад, когда я был очень счастлив, что он достиг отметки 8000, через несколько недель, еще через неделю после этого снова было 500. И это происходило снова и снова.

Понятия не имею, почему. Почему?

Ответы [ 3 ]

7 голосов
/ 01 ноября 2010

Возможно, вы страдаете от состояния гонки в файловой системе, вы пытаетесь открыть и прочитать файл, затем открыть тот же файл и записать в него.Операционная система, возможно, не полностью освободила свою первоначальную блокировку файла, когда вы закрываете его для чтения, а затем сразу же открываете для повторной записи.Если сайт так занят, как вы говорите, то у вас могут возникнуть проблемы с несколькими экземплярами сценария, пытающимися получить доступ к файлу одновременно

Если этого не сделать, все операции с файлами выполняйте за один раз.Если вы используете fopen (), flock (), fread (), rewind (), fwrite () и fclose () для обработки обновления счетчика посещений, вы можете избежать необходимости закрывать файл и открывать его снова.Если вы используете режим r +, вы сможете прочитать значение, увеличить его и записать результат за один раз.

Ничто из этого не может полностью гарантировать, что вы не столкнетесь с проблемами при одновременном доступе.
Я настоятельно рекомендую рассмотреть другой подход к реализации вашего счетчика посещений, такой как счетчик, управляемый базой данных.

2 голосов
/ 01 ноября 2010

Всегда выполняйте правильную обработку ошибок, а не просто подавляйте ошибки с помощью @.В этом случае, вероятно, что file_get_contents не удалось, так как файл был записан в то время.Таким образом, $hit_count устанавливается на FALSE, а $hit_count++ делает его 1.Таким образом, ваш счетчик случайным образом сбрасывается на 1 при сбое чтения.

Если вы настаиваете на записи числа в файл, выполняйте надлежащую проверку ошибок и пишите в файл только в том случае, если вы УВЕРЕНЫ, что получили файлopen.

$hit_count = file_get_contents('download.txt');

if($hit_count !== false) {
    $hit_count++;
    file_put_contents('download.txt', $hit_count);
}

header('Location: file/xxx.zip');

Время от времени он все равно будет отказывать, но по крайней мере он не будет усекать ваш счетчик.

0 голосов
/ 01 ноября 2010

Это своего рода ситуация, когда наличие базы данных, записывающей посещения (что позволило бы более эффективно анализировать данные, так как их можно было бы отслеживать по дате, времени, рефереру, местоположению и т. Д.), Было бы лучшим решением, чем использование счетчика. в плоском файле.

Причиной может быть то, что у вас возникла коллизия между действием чтения и записи в файле (происходит один раз каждые 8000 экземпляров или около того). Добавление флага LOCK_EX к действию file_get_contents() PHP Reference может предотвратить это, но я не могу быть уверен на 100%.

Лучше посмотреть на запись данных в базу данных, поскольку это почти наверняка предотвратит вашу текущую проблему потери счета.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...