Работа с индексным файлом: запись, извлечение, редактирование и удаление
Еще одной распространенной задачей является работа с индексными файлами. Пусть имеется файл index.txt следующего формата:
1 Программирование
2 Программирование на РНР
3 Программирование на JavaScript
4 Программирование на ASP.NET
Каждому номеру, который обычно называют индексом, соответствует строка, называемая значением. Одной из насущных задач является определение наличия в файле заданного индекса и вывод соответствующего ему значения, если такой индекс существует. Данную задачу решает скрипт приведенный ниже.
<?php
//ищем строку с индексом 2
$index=2;
//имя файла
$filename="index.txt";
//открываем файл для чтения
$fd=fopen($filename, "r");
//читаем содержимое файла
$bufer=fread($fd, filesize($filename));
//закрываем файл
fclose($fd);
//находим строку с индексом $index
preg_match("|$index([^\n]*)|", $bufer, $matches);
//выводим результат
if(isset($matches[1])) echo $matches[1];
else echo "Позиция не найдена";
?>
Для вставки уникального индекса в файл необходимо определить максимальный индекс и увеличить его на единицу. Эта задача решается ниже приведенном скрипте:
<?php
//имя файла
$filename="index.txt";
//помещаем содержимое файла в массив $lines
$lines=file($filename);
//в цикле формируем массив индексов
foreach($lines as $line)
{
//обнуляем массив
unset($matches);
//находим строку с индексом $index
preg_match("|^[\d]+|", $line, $matches);
if(isset($matches)) $index[]=$matches[0];
}
//находим максимальное значение массива
//$index и увеличиваем его на единицу
echo max($index)+1;
?>
Примечание. При таком подходе при увеличении объема файла время на поиск максимального значения будет расти, поэтому целесообразно хранить максимальный индекс в отдельном файле, переписывая его при каждом добавлении уникального индекса в файл.
Теперь, когда новый уникальный индекс получен, можно добавить новую запись в файл.
<?php
//имя файла
$filename="index.txt";
//открываем файл для записи
$fd=fopen($filename, "a");
//добавляем новую запись
fwrite($fd, "5 Новая строка\n");
//закрываем файл
fclose($fd);
?>
В конце строки следует поместить символ перевода строки \n
, иначе новая запись окажется не на новой строке, а в конце последней записи. После работы функции будет добавлена новая строка, в результате чего файл index.txt примет вид:
1 Программирование
2 Программирование на РНР
3 Программирование на JavaScript
4 Программирование на ASP.NET
5 Новая строка>
Еще одной интересной задачей является редактирование отдельных записей файла. Эту задачу решает небольшое веб-приложение, расположенное в файле edit.php, код которого расположен ниже.
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Файл edit.php</title>
</head>
<body>
<?php
//edit.php
//имя файла
$filename="index.txt";
//если передано исправленное содержимое файла,
//открываем файл и перезаписываем его
if(isset($_POST['content']))
{
//открываем файл для чтения
$fd=@fopen($filename, "r");
//читаем содержимое буфера в переменную $bufer
$bufer=fread($fd, filesize($filename));
//закрываем файл
fclose($fd);
//изменяем строку с индексом $_POST['index']
$parent="|".$_POST['index']."[^\n]*\n|";
$replacement=$_POST['content'];
$bufer=preg_replace($parent, $replacement, $bufer);
//открываем файл для записи
$fd=@fopen($filename, "w");
//перезаписываем содержимое файла
fwrite($fd, $bufer);
//закрываем файл
fclose($fd);
//помещаем в суперглобальный массив $_GET имя файла
$_GET['index']=$_POST['index'];
}
?>
<form action="edit.php" method="get" name="first">
Номер записи <br>
<input name="index" type="text" value="<?php echo $_GET['index'];?>" size="25">
<br>
<input name="" type="submit" value="Отправить">
</form>
<?php
//если строке запроса передан индекс,
//открываем его для редактирования
if(isset($_GET['index']))
{
//помещаем содержимое файла в массив $lines
$lines=file($filename);
if($_GET['index']<1 || $_GET['index']>count($lines))
{
exit("К сожалению такая запись не существует");
}
?>
<form action="edit.php" method="post" name="stcond">
<textarea name="content" cols="50" rows="10">
<?php echo $lines[$_GET['index']-1]; ?>
</textarea><br>
<input name="index" type="hidden" value="<?php echo $_GET['index'];?>">
<input name="edit" type="submit" value="Редактировать">
</form>
<?php
}
?>
</body>
</html>
В скрипте определяются две формы, первая их которых, first
, содержит текстовое поле index
для номера записи из файла index.txt
и кнопку для отправки данных обработчику, в качестве которого выступает этот же самый скрипт. Форма будет выглядеть так:
После ввода в форму номера записи страница перезагружается, и обработчик, следующий сразу за формой, помещает содержимое файла в массив $lines
. Если массив содержит элемент с индексом, переданным из первой формы, то происходит вывод второй формы stcond
, содержащей текстовую область для редактирования записи.
Кроме того, форма имеет скрытое поле index, через которое передается индекс редактируемой записи.
После редактирования содержимого записи данные повторно отправляются скрипту в файле edit.php
, но уже методом POST
. В дело вступает обработчик, расположенный в начале файла. Он помещает содержимое редактируемого файла во временную переменную $bufer
, содержимое которой редактируется при помощи функции preg_replace()
. После того как содержимое файла исправлено в переменной $bufer
, происходит перезапись файла ее содержимым.
Последняя задача, которая может быть полезна при работе с индексными файлами — удаление записи с определенным индексом. Данная задача решается при помощи скрипта, представленного ниже.
<?php
//индекс строки
$index=2;
//имя файла
$filename="index.txt";
//открываем файл для чтения
$fd=fopen($filename, "r");
//читаем содержимое файла
$bufer=fread($fd, filesize($filename));
//закрываем файл
fclose($fd);
//удаляем строку с индексом $index
$bufer=preg_replace("|$index [^\n]*\n|", "", $bufer);
//открываем файл для записи
$fd=fopen($filename, "w");
//перезаписываем содержимое файла
fwrite($fd, $bufer);
//закрываем файл
fclose($fd);
?>
В результате работы скрипта содержимое файла index.txt изменится следующим образом:
1 Программирование
3 Программирование на JavaScript
4 Программирование на ASP.NET
5 Новая строка
Блокировка файла
Рассмотренные выше скрипты осуществляют запись в файл в предположении, что скрипт владеет файлом единолично, но при записи в файл одновременно несколькими пользователями могут возникнуть конфликтные ситуации, приводящие к разрушению информации в файле.
Примечание. На веб-сленге операцию блокировки файла часто называют "залачиванием". Сленговое словечко "залачивать" происходит от английского глагола to lock
— закрывать.
В РНР для предотвращения такой ситуации имеется специальная функция flock()
, которая блокирует файл, не позволяя другим пользователям читать этот файл или писать в него до тех пор, пока процесс, наложивший блокировку, не закончит работу с файлом. Синтаксис функции flock()
следующий:
bool flock(resource fd, int operation [, int &wouldblock])
В качестве первого аргумента функция принимает дескриптор файла, возвращаемый функцией fopen()
. В качестве второго аргумента функции передается константа, сообщающая тип операции, совершаемой над файлом. Допустимы следующие значения:
LOCK_SH
— чтение файла несколькими потоками;LOCK_EX
— блокировка для использования файла одним потоком(для записи);LOCK_UN
— снятие блокировки с файла, когда оно больше не требуется, чтобы остальные участники могли получить к нему доступ.
Третий необязательный параметр wouldblock
устанавливается в true
, если файл, к которому происходит обращение, уже блокирован другим скриптом.
Функцию flock()
следует вызывать сразу после открытия файла для установки блокировки и непосредственно перед закрытием файла для снятия блокировки.
Пример:
<?php
//имя файла
$filename="index.txt";
//открываем файл для записи
$fd=fopen($filename,"w");
//блокируем файл
flock($fd, LOCK_EX);
//перезаписываем содержимое файла
fwrite($fd, "Текст для записи в файл index.txt");
//снимаем блокировку с файла
flock($fd,LOCK_UN);
//закрываем файл
fclose($fd);
?>
В реальных веб-приложениях необходимы более сложные схемы блокировки файлов. Так при добавлении записи в файловый вариант гостевой книги, чата или счетчика посещений, если файл заблокирован предыдущей операцией, информация будет потеряна, поэтому следует организовать цикл, как это продемонстрировано ниже.
<?php
function work_with_file($filename, $str)
{
//открываем файл
if($fd=@fopen($filename, "a"))
{
//в течении 10 секунд пытаемся получить
//единоличный доступ к файлу
for($i=0; $i<10; ++$i)
{
//как только доступ получен выходим из цикла
if(flock($fd, LOCK_EX)) break;
//задерживаем время выполнения программы на 1секунду,
//если доступ получить не удалось
else sleep(1);
}
//записываем строку в файл
fwrite($fd, $str);
//очищаем буфер записи
flush($fd);
//снимаем блокировку с файла
flock($fd, LOCK_UN);
//закрываем файл
fclose($fd);
//покидаем функцию
return true;
}
else
{
error("Нет доступа к файлу или он не существует!", $file);
return false;
}
}
?>
В данном скрипте представлена функция work_with_file()
, которая в качестве первого параметра $filename
принимает имя файла, а вкачестве второго параметра $str
— информацию, которую необходимо дописать в файл. При этом блокировка файла осуществляется в цикле: при неудачной попытке заблокировать файл происходит задержка выполнения программы с помощью функции sleep()
, которая принимает единственный параметр — время— задержки в секундах.
Сохранение и извлечение из файла массивов и объектов
Осуществить упаковку и распаковку соответственно, массивов и объектов позволяют функции serialize()
и unserialize()
.
serialize($obj
) — возвращает строку, являющуюся упакованным эквивалентом некоего объекта$obj
, переданного в первом параметре. При этом совершенно не важно, что это за объект: массив или целое число ... Да что угодно.unserialize($str)
— принимает в лице своего параметра$str
строку, ранее созданную при помощиserialize()
, и возвращает целиком объект, который был упакован.
Эти функции удобно использовать при работе с файлами, т.к. упакованный в строку массив нужно где-то хранить.
<?php
$poll[0]=23;
$poll[1]=45;
$poll[2]=34;
$poll[3]=2;
$poll[4]=12;
//упаковываем массив в строку
$str=serialize($poll);
//помещаем строку в файл
$fd=fopen("text.txt","w");
//сохраняем в файле упакованный массив
fwrite($fd, $str);
//закрываем файл
fclose($fd);
?>
После того как упакованный массив сохранен в файле, в другом скрипте его можно извлечь при помощи кода, представленного ниже.
<?php
//открываем файл
$fd=fopen("text.txt", "r");
//читаем содержимое файла во временную переменную $bufer
$bufer=fread($fd, filesize("text.txt"));
//закрываем файл
fclose($fd);
//извлекаем массив из переменной $bufer
$arr=unserialize( $bufer);
//выводим дамп массива
print_r($arr);
?>
Работа с csv-файлами. Загрузка данных из MS Excel
Для чтения файлов с расширением csv применяется функция fgetcsv()
.
array fgetcsv(int file, int length, char delim)
— читает строку из файла и разбивает ее по символуdelim
. Строковой параметрdelim
должен содержать только один символ, иначе учитывается лишь первый символ строки. Функция возвращает получившийся массив илиfalse
, если достигнут конец файла. Пустые строки в файле не игнорируются, а возвращаются как массив из одного элемента — пустой строки. Параметр length задает максимальную длину строки точно так же, как делается в функцииfgets()
.
Формат CSV является одним из форматов, в котором можно сохранять файлы MS Excel
. Ниже приведен пример чтения созданного MS Excel файла file.csv
, содержащего пароли пользователей.
<?php
//имя файла
$filename="file.csv";
//открываем файл
$fd=fopen("file.csv", "r");
//в цикле читаем строки файла
while($data=fgetcsv($fd, 1000, ";"))
{
foreach($data as $element) echo "$element ";
echo "<br>";
}
//закрываем файл
fclose($fd);
?>
Комментарии(0)
Для добавления комментариев надо войти в систему и авторизоватьсяКомментирование статей доступно только для зарегистрированных пользователей:Зарегистрироваться