Офис НП AMWAY в Ярославле
Купить продукцию Амвей в Ярославле
На карте Купить AMWAY в ЯрославлеПриобрести высококачественную продукцию Амвей в Ярославле, получить консультации по бизнесу, заказать продукцию или получить заказ:
Адрес: улица Валентины Терешковой, дом 1 (Вход со двора)
Телефон: +7 (920) 112-00-91
Email: matyxho@mail.ru
Сайт: https://www.amway.ru/user/lebedem
Визитка: http://yar.meweb.ru
Иерархия статей
Статьи » Программирование » PHP: Удаление строки из файла
Сниппет
Я понимаю, что запись в файл сейчас, скорее, исключение, однако иногда подобное может понадобиться. Но в статье буду рассматривать не саму запись, а удаление определенной строки из файла.
PHP: Удаление строки из файла
Опубликовал  Pisatel Добавлено  16-03-2015 20:54 16 Март 2015 20:54:02 1890  Прочтений 1890 Прочтений  4 Комментариев 4 Комментариев
Обновлено: 10-06-2015 12:33 Обновлено: 10 июня 2015 12:33:27  printer
Недавно понадобилось мне удалить строку из файла. Так как ранее о записи в файл я имел весьма смутное представление, решил немного погуглить. Вариантов выдало много, но все они были однотипные, видимо, кто-то один придумал, а остальные лишь подхватили данное решение, каждый добавив что–то свое: ну, типа, рерайт. Меня же во всех этих примерах не устраивало несколько обстоятельств: там везде был задействован цикл for, нигде, ни в одном из примеров, не была учтена буферизация (запись в файл по 8кб), что при нагруженности ресурса и одновременно нескольких потоках записи могло бы привести к "микшированию" данных: то есть, 8кб от одного потока, 8кб от другого, затем опять 8кб от первого... Практически ни в одном из найденных примеров не была реализована блокировка файла во время записи, что также могло привести к потере данных (всех или части). Ко всему прочему, почти во всех примерах использовалась языковая конструкция unset(), хотя почти во всех случаях работа шла с элементами массива. А что у нас самое лучшее для перебора массивов в пэхапэ? Правильно, конструкция foreach. Доказано, что эта конструкция работает с массивами быстрее, чем, например, for (пруф). Именно поэтому я и решил написать свой велосипед удаления строки из файла, а ты уж сам решай, уважаемый читатель, кто прав, а кто виноват.

Итак, пример будет реальный. Возьмем для записи файл .htaccess, чтобы максимально обострить чувство опасности при работе с ним. Например наш файл имеет такое содержимое:

Код: APACHE
DefaultLanguage ru

AddDefaultCharset windows-1251

ErrorDocument 404 /404.php

Options -Indexes

RewriteEngine on

RewriteCond %{HTTP_HOST} ^meweb\.ru$ [NC]

RewriteRule ^(.*)$ http://www.meweb.ru/$1 [R=301,L]

RewriteBase /




Что бы нам удалить? Ну давайте, например, RewriteEngine on. Далее пойдет немного кода, безусловно, с подробными пояснениями:

Код: PHP
    $htu = ".htaccess"; // задали путь к .htaccess для удобства

if ($fh = fopen($htu, "a+b")) { // открыли файл для чтения и записи, поместив указатель в конец

$lines = file_get_contents($htu); // прочитали файл в строку

$lines = explode("\n", $lines); // превратили строку в массив

// далее проверим, массив ли получился и найдем искомую строку

if (is_array($lines) && ($sline = array_search("RewriteEngine on", $lines)) !== false) {

// функция array_search вернула нам ключ нужной строки

// ну а далее- идем по массиву, и, найдя нужное значение, удаляем его

foreach ($lines as $key => $val) { // в переменной $vаl- значение, в $key- ключ значения

if ($key == $sline) continue; // именно это выражение удалит нужное значение

$lnht[] = $val; // собираем массив без искомого значения

}

} else {

$lnht = $lines; // иначе, если искомое значение не обнаружено, просто возвращаем все, что было в файле

}

$lnht = implode("\n", $lnht); // превращаем обратно массив в строку

// а далее- проверяем, можно ли вести запись в файл и сработает ли блокировка файла

if (is_writable($htu) && flock($fh, LOCK_EX | LOCK_NB)) {

ftruncate($fh, 0); // очищаем полностью файл

stream_set_write_buffer($fh, 0); // отключаем буферизацию, дабы не возникло ошибки при записи (теперь запись будет произведена полностью, а не по 8кб)

fwrite($fh, $lnht); // пишем в файл

flock($fh, LOCK_UN); // снимаем блокировку с файла

}

fclose($fh); // закрываем файл

clearstatcache(); // чистим кэш (в данном случае нужно лишь для функции is_writable, так как ее результат кэшируется)

}




Если мы "раздампим" после explode() переменную $lines, то увидим примерно такую структуру массива:

Код: PHP
array(8) {

[0]=> string(19) "DefaultLanguage ru "

[1]=> string(31) "AddDefaultCharset windows-1251 "

[2]=> string(27) "ErrorDocument 404 /404.php "

[3]=> string(17) "Options -Indexes "

[4]=> string(17) "RewriteEngine on "

[5]=> string(42) "RewriteCond %{HTTP_HOST} ^meweb\.ru$ [NC] "

[6]=> string(52) "RewriteRule ^(.*)$ http://www.meweb.ru/$1 [R=301,L] "

[7]=> string(14) "RewriteBase / "

}




То есть нужное нам значение имеет ключ 4 (не забываем, что отсчет начинается с 0). Но это так, для наглядности.

Вот и все. В итоге после записи в файл мы получим

Код: APACHE
DefaultLanguage ru

AddDefaultCharset windows-1251

ErrorDocument 404 /404.php

Options -Indexes

RewriteCond %{HTTP_HOST} ^meweb\.ru$ [NC]

RewriteRule ^(.*)$ http://www.meweb.ru/$1 [R=301,L]

RewriteBase /




То есть, нужная нам строка будет успешно удалена, а файл безопасно перезаписан. Если мы вместо оператора (управляющей конструкции) continue; используем оператор break;, то цикл остановится на нужном нам значении массива и данные, которые будут ниже искомого значения (в том числе и оно) не запишутся: кому–то может понадобиться именно такой вариант.

На этом пока все. Всем всего доброго.
Понравилась статья?
Метки для данной статьи
Поделиться:   
Комментарии
#1 | Vitalij 18 марта 2015 16:11:14
No Avatar
Гость
Ну почему раньше эту статью не нашел! буквально пару месяцев назад мчился спасибо!
#2 | Vitalij 18 марта 2015 16:18:41
No Avatar
Гость
Мучился))) а можно чуть подробнее чем отличается break от continue?
Avatar
Отсутствует
Супер Администратор
Активный
С 03. февраля 2013
Vitalij, всегда пожалуйста. Вкратце о continue vs break: оператор continue при переборе массива пропустит значение, заданное условием, но перебор массива при этом не закончится и будет продолжен. Оператор же break прервет перебор массива, остановившись на значении, заданном в условии. Поэтому, если понять, как работают эти операторы, можно значительно упростить и сократить код.
Я не европеец. И не азиат. Я русский. Я россиянин. Я за истинные семейные христианские ценности. И это - моя национальная идея.
#4 | Vitalij 18 марта 2015 20:43:35
No Avatar
Гость
Спасибо!
Добавить комментарий
Имя:

Проверочный код:
Последние активные темы форума
  Темы Просмотров Ответов Последние сообщения
folder Вопрос по переделке bb-кода
PHP, MySQL
2136 5 Pisatel
26. мая 2017
folder Вопросы по Ajax форме обратной связи
CMS PHP Fusion
9506 48 Ditrin
19. февраля 2017
folder BBCode YouTube Video Colorbox mod
CMS PHP Fusion
6821 2 Pisatel
10. декабря 2016
folder Как лучше создать собственную страницу?
CMS PHP Fusion
5436 17 Pisatel
11. мая 2016
folder Небольшие вопросы по скриптам магазина и катало...
PHP, MySQL
45409 80 Pisatel
11. января 2016
folder BBCode Code mod
CMS PHP Fusion
3319 0 Pisatel
31. августа 2015
folder Ajax Like Dislike Article Panel
CMS PHP Fusion
6673 16 Pisatel
07. июля 2015
folder Хлебные крошки / BreadCrumbs SEO Panel
CMS PHP Fusion
7323 17 Pisatel
04. июля 2015
folder Abbr Description BBCode
CMS PHP Fusion
2469 0 Pisatel
15. июня 2015
folder Плагин Email рассылки Mail To All by Pisatel
CMS PHP Fusion
10320 32 Pisatel
26. апреля 2015
folder Подозрительный трафик и прочие страшилки
Всякая хрень
4513 2 Ditrin
23. апреля 2015
folder Мод Newsletter - рассылка писем пользователям с...
CMS PHP Fusion
6276 13 Pisatel
10. апреля 2015
folder Мод отправки писем PHPMailer для PHP-Fusion
CMS PHP Fusion
32945 113 Ditrin
06. апреля 2015
folder Появление неизвестного файла subscriptions.php
CMS PHP Fusion
3135 2 Pisatel
06. апреля 2015
folder Autoban on IP
CMS PHP Fusion
12170 13 Pisatel
03. апреля 2015