Форум программистов, компьютерный форум, киберфорум
PHP для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.78/9: Рейтинг темы: голосов - 9, средняя оценка - 4.78
0 / 0 / 0
Регистрация: 01.10.2020
Сообщений: 6
1

Проверка на наличие строки в файле с последующей записью

01.10.2020, 00:56. Показов 1793. Ответов 10
Метки php (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте, уважаемые пользователи форума. Только зарегистрировался, прошу простить меня, если вопрос будет некорректным.

Необходимо проверить наличие строки в файле crm.txt. Если строки нет, то записать строку в конец файла c новой строки. Для того, чтобы файл оставался легким, при достижении 10 строк, удалять первую запись. При работе с файлом, запретить запись другим процессом. Если искомая строка есть в файле, то ничего не делать.

PHP
1
2
3
4
5
6
$file=file('crm.txt');
if(in_array($file,$str)){
    exit;
} else {
    file_put_contents($file, $str . PHP_EOL, FILE_APPEND | LOCK_EX);
}
Пример искомой строки:
http://192.168.0.10:5858/newor... riy&order=[{"menuid":"171","quant":"1.00"}]

Помогите пожалуйста, несколько дней бьюсь, застрял на этом моменте, а время поджимает.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.10.2020, 00:56
Ответы с готовыми решениями:

Визуализировать DataTable и возможность добавления строки с последующей ее записью в файл
Здравствуйте! Возникла, казалось бы простая задача. Нужно считывать данные их csv файла в...

Разделение строки на 2 подстроки с последующей записью последних в HashMap<String, String>
Дорбого времени суток. Застрял на такой глупости блок кода который читает построчно тхт файл и...

Проверка на наличие записи в файле
Доброго времени суток, с пхп почти не знаком, эксперементирую, и столкнулся с проблемой. Требуется...

Проверка на наличие строчки в текстовом файле (ini иле txt)
Всем доброго времени суток дороги пользователи портала! Сегодня я снова столкнулся с проблемой при...

10
Невнимательный
2623 / 998 / 327
Регистрация: 08.02.2013
Сообщений: 5,858
Записей в блоге: 2
01.10.2020, 02:25 2
Цитата Сообщение от Abu-Jasmin Посмотреть сообщение
запретить запись другим процессом
Если немного изменить пример из описания flock()
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$str='.....';
$file = array();
$fp = fopen("crm.txt", "r+");
if (flock($fp, LOCK_EX)) { // выполняем эксклюзивную блокировку
    while(!feof($fp)) $file[] = trim(fgets($fp));
    if(!in_array($file,$str)) {
        rewind($fp);
        ftruncate($fp, 0); // очищаем файл
        if(count($file) > 9) array_shift($file);
        # Возможно просто $file = array_slice($file, -9);
        while(($txt=array_shift($file)) !== NULL)
            fwrite($fp, $txt ."\n");
        fwrite($fp, $str ."\n");
        fflush($fp);        // очищаем вывод перед отменой блокировки
    }
    flock($fp, LOCK_UN); // снимаем блокировку
} else {
    echo "Не удалось получить блокировку!";
}
fclose($fp);
то наверно это оно... т.к. если не блокировать даже во время чтения то нужно сначала просто прочитать,
потом если нужно добавление уже блокировать и читать-проверять снова
т.к. возможно между чтением и блокировкой кто-то уже перезаписал.

Но если много процессов часто делают это с этим файлом, но мало туда пишут
... то даже не знаю )
может так и надо делать.

Код не проверял, забэкапьте crm.txt

Добавлено через 5 минут
Цитата Сообщение от x_lab Посмотреть сообщение
if(count($file) > 9) array_shift($file);
# Возможно просто $file = array_slice($file, -9);
Проверил
можно просто без проверки дёргать максимум 9 крайних элеиентов
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
cat <<\x | /c/t/usr/php74/php
 
<?php
var_export( array_slice([1,2,3,4,5], -9));
var_export( array_slice([1,2,3,4,5,6,7,8,9,10,11,12], -9));
x
 
array (
  0 => 1,
  1 => 2,
  2 => 3,
  3 => 4,
  4 => 5,
)array (
  0 => 4,
  1 => 5,
  2 => 6,
  3 => 7,
  4 => 8,
  5 => 9,
  6 => 10,
  7 => 11,
  8 => 12,
)
0
Эксперт PHP
4925 / 3920 / 1620
Регистрация: 24.04.2014
Сообщений: 11,441
01.10.2020, 11:55 3
Цитата Сообщение от x_lab Посмотреть сообщение
"r+"
Возможно лучше было бы c+, r+ не будет работать если файла нет
Цитата Сообщение от x_lab Посмотреть сообщение
Но если много процессов часто делают это с этим файлом, но мало туда пишут
... то даже не знаю )
Если нужно только чтение, то использовать флаг LOCK_SH при блокировке, если еще и запись, то LOCK_EX
1
0 / 0 / 0
Регистрация: 01.10.2020
Сообщений: 6
01.10.2020, 23:10  [ТС] 4
Спасибо за ответ!

Код работает только частично: запись в файл до 10 строк идет нормально.

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

Может ли быть причина в самой строке? Может строку как-то модифицировать, чтобы проверка проходила успешно?
Строка поступает в подобном виде, с разными или совпадающими параметрами:
http://192.168.0.10:5858/newor... riy&order=[{"menuid":"171","quant":"1.00"}]
0
Невнимательный
2623 / 998 / 327
Регистрация: 08.02.2013
Сообщений: 5,858
Записей в блоге: 2
02.10.2020, 00:00 5
Цитата Сообщение от Abu-Jasmin Посмотреть сообщение
запись продолжается.
После строки
PHP
5
    while(!feof($fp)) $file[] = trim(fgets($fp));
добавьте
PHP
1
2
echo "<xmp>", var_export($file, 1), "\n-----------\n",
  var_export($str, 1), "</xmp>";
что видно? есть отличия?
0
0 / 0 / 0
Регистрация: 01.10.2020
Сообщений: 6
02.10.2020, 00:19  [ТС] 6
добавил, только не понимаю где посмотреть вывод от echo.

запись также продолжается.
0
Невнимательный
2623 / 998 / 327
Регистрация: 08.02.2013
Сообщений: 5,858
Записей в блоге: 2
02.10.2020, 01:41 7
Цитата Сообщение от Abu-Jasmin Посмотреть сообщение
где посмотреть вывод
В браузере не вариант запустить ,) .... или из коммандной строки?
можно в файл какой-нибудь попробовать скинуть
типа file_put_contents('test.txt', var_export($file, 1). "\n-----------\n". var_export($str, 1););
0
0 / 0 / 0
Регистрация: 01.10.2020
Сообщений: 6
03.10.2020, 01:00  [ТС] 8
Вставил в код, теперь в файле test.txt пишет такие данные:
array (
0 => '',
1 => 'http://192.168.0.10:5858/neworder?orderformattype=1&client=%D1%82%D0%B5%D1%81%D1%82&phone=+79876543210&st reet=%D0%A3%D0%BB%D0%B8%D1%86%D0%B0%3A&comment=%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1 %87%D0%B0%D0%BD%D0%B8%D0%B5%3A&flatwarecount=1&order=[{"menuid":"253","quant":"1.00"}]',
2 => '',
3 => 'http://192.168.0.10:5858/neworder?orderformattype=1&client=%D1%82%D0%B5%D1%81%D1%82&phone=+79876543210&st reet=%D0%A3%D0%BB%D0%B8%D1%86%D0%B0%3A&comment=%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1 %87%D0%B0%D0%BD%D0%B8%D0%B5%3A&flatwarecount=1&order=[{"menuid":"253","quant":"1.00"}]',
4 => '',
5 => 'http://192.168.0.10:5858/neworder?orderformattype=1&client=%D1%82%D0%B5%D1%81%D1%82&phone=+79876543210&st reet=%D0%A3%D0%BB%D0%B8%D1%86%D0%B0%3A&comment=%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1 %87%D0%B0%D0%BD%D0%B8%D0%B5%3A&flatwarecount=1&order=[{"menuid":"253","quant":"1.00"}]',
6 => '',
7 => 'http://192.168.0.10:5858/neworder?orderformattype=1&client=%D1%82%D0%B5%D1%81%D1%82&phone=+79876543210&st reet=%D0%A3%D0%BB%D0%B8%D1%86%D0%B0%3A&comment=%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1 %87%D0%B0%D0%BD%D0%B8%D0%B5%3A&flatwarecount=1&order=[{"menuid":"253","quant":"1.00"}]',
8 => '',
9 => 'http://192.168.0.10:5858/neworder?orderformattype=1&client=%D1%82%D0%B5%D1%81%D1%82&phone=+79876543210&st reet=%D0%A3%D0%BB%D0%B8%D1%86%D0%B0%3A&comment=%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1 %87%D0%B0%D0%BD%D0%B8%D0%B5%3A&flatwarecount=1&order=[{"menuid":"253","quant":"1.00"}]',
10 => '',
)
-----------
'http://192.168.0.10:5858/neworder?orderformattype=1&client=%D1%82%D0%B5%D1%81%D1%82&phone=+79876543210&st reet=%D0%A3%D0%BB%D0%B8%D1%86%D0%B0%3A&comment=%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1 %87%D0%B0%D0%BD%D0%B8%D0%B5%3A&flatwarecount=1&order=[{"menuid":"253","quant":"1.00"}]'

Строка повторяется.
0
Невнимательный
2623 / 998 / 327
Регистрация: 08.02.2013
Сообщений: 5,858
Записей в блоге: 2
03.10.2020, 03:27 9
Цитата Сообщение от x_lab Посмотреть сообщение
PHP
6
    if(!in_array($file,$str)) {
Только сейчас заметил... ... параметры наоборот, я тупо скопировал.
Должно быть так
PHP
1
    if(!in_array($str, $file)) {
Не пойму из-за чего пустые строки в файле
... как-будто из-за того что у Вас в переменной $str перенос строки...
вроде var_export() не показало в $tr перенос
при чтении в массив стоит trim(fgets($fp));
в массиве сами строки без переносов ...
поэтому добавляется где
PHP
1
2
3
4
        while(($txt=array_shift($file)) !== NULL)
            fwrite($fp, $txt ."\n");
        fwrite($fp, $str ."\n");
        fflush($fp);
Непонятно как так получается но скорее всего в строке
$str не всегда без переноса, можно попробовать где-то в начале сделать $str=trim($str);
Но можно переделать все эти места под работу только со строкой с перенсом
0
0 / 0 / 0
Регистрация: 01.10.2020
Сообщений: 6
03.10.2020, 23:50  [ТС] 10
Ура! Проверка строки на дубль работает, аналогичные строки не записываются.

Правда с переносом так и не разобрался, пустая строка все равно добавляется. И ещё, видимо из-за пустой строки счетчик сбивается, запись продолжала добавляться и дошла до 13 строк (больше не проверял).

Пробовал вместо "r+" написать "a+", результат тот же.

В самом начале кода как вы говорили, написал так:

$str = trim($str);
$file = array();
...
Пустая строка все равно добавляется.
Может причина в этой строке: $file = array();

Привожу получившийся код целиком:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$str = trim($str);
$file = array();
$fp = fopen("crm.txt", "r+");
if (flock($fp, LOCK_EX)) {
    while(!feof($fp)) $file[] = trim(fgets($fp));
    file_put_contents('test.txt', var_export($file, 1). "\n-----------\n". var_export($str, 1));
    if(!in_array($str, $file)) {
        rewind($fp);
        ftruncate($fp, 0); // очищаем файл
        if(count($file) > 9) array_shift($file);
        while(($txt=array_shift($file)) !== NULL)
            fwrite($fp, $txt ."\n");
        fwrite($fp, $str ."\n");
        fflush($fp);        // очищаем вывод перед отменой блокировки
    }
    flock($fp, LOCK_UN); // снимаем блокировку
} else {
    echo "Не удалось получить блокировку!";
}
fclose($fp);
Добавлено через 17 минут
С пустой строкой разобрался:
убрал один перенос строки:
PHP
1
2
3
4
5
while(($txt=array_shift($file)) !== NULL)
            fwrite($fp, $txt ."\n");
            fwrite($fp, $str); // убрал  ."\n"
            //fwrite($fp, $str ."\n");
            fflush($fp);
Добавлено через 6 минут
И с количеством строк всё чётко.

В общем, БОЛЬШОЕ СПАСИБО, x_lab, здорово помог!

Теперь буду испытывать этот код на реальной работе с срм. Позже отпишусь.

Добавлено через 1 минуту
Для тех, кому может понадобится подобное решение:

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$str = $crm_get;
$file = array();
$fp = fopen("crm.txt", "r+");
if (flock($fp, LOCK_EX)) {
    while(!feof($fp)) $file[] = trim(fgets($fp));
    // file_put_contents('test.txt', var_export($file, 1). "\n-----------\n". var_export($str, 1)); // для проверки поступающих на запись строк
    if(!in_array($str, $file)) {
        rewind($fp);
        ftruncate($fp, 0); // очищаем файл
        if(count($file) > 9) array_shift($file);
        while(($txt=array_shift($file)) !== NULL)
            fwrite($fp, $txt ."\n");
            fwrite($fp, $str);
            fflush($fp);        // очищаем вывод перед отменой блокировки
    }
    flock($fp, LOCK_UN); // снимаем блокировку
} else {
    echo "Не удалось получить блокировку!";
}
fclose($fp);
0
Невнимательный
2623 / 998 / 327
Регистрация: 08.02.2013
Сообщений: 5,858
Записей в блоге: 2
04.10.2020, 01:07 11
Цитата Сообщение от Abu-Jasmin Посмотреть сообщение
PHP
10
     if(count($file) > 9) array_shift($file);
в этой строке просто удаляется первый элемент массива, если элементов > 9

теоретически если добавлялось по две строки за раз, то количество строк росло.
Но если-бы добавлялось по одной, то не превысило-бы 10
замена на такую строку
PHP
10
     $file = array_slice($file, -9);
из любого количества сделает максимум 9 последних элементов.

Цитата Сообщение от Abu-Jasmin Посмотреть сообщение
один перенос строки:
как-то странно... если использовалось trim($str)
то почему fwrite() добавляло перенос.
... по fwrite() нашёл такое
Замечание:
В системах, различающих двоичные и текстовые файлы (к примеру, Windows), файл должен быть открыт используя флаг 'b' в конце аргумента mode функции fopen().
то есть предлагается сделать
PHP
3
$fp = fopen("crm.txt", "rb+");
возможно это было причиной

если открывать с 'ab+' то да ... с одной стророны будет создаваться новый файл, если не существует
по с другой стороныы перед чтением нужно будет выполнить
PHP
1
2
fseek($fp, 0);
// или так-же как там rewind($fp); но ещё раз и непосредственно до или после блокировки
чтобы от конца файла перейти к началу
и неизвестно какоё могла быть рабочая директоория, а в fopen у Вас относительный путь к файлу
и файл как-бы где-попало тоже не стоит создавать ))

Добавлено через 51 минуту
Можно попробовать 'cb+' вместо 'rb+'
'c' Открывает файл только для записи. Если файл не существует, то он создается. Если же файл существует, то он не обрезается (в отличие от 'w'), и вызов к этой функции не вызывает ошибку (также как и в случае с 'x'). Указатель на файл будет установлен на начало файла. Это может быть полезно при желании заблокировать файл (см. flock()) перед изменением, так как использование 'w' может обрезать файл еще до того как была получена блокировка (если вы желаете обрезать файл, можно использовать функцию ftruncate() после запроса на блокировку).
'c+' Открывает файл для чтения и записи; в остальном имеет то же поведение, что и 'c'.
Файл создастся если не существовал, но перемотка на начало не нужна , как при 'a+'
и там какое-то странное приммечание с этим 'a+' что мол несмотря на fseek() запись всегда в конец файла

Но наверное я-бы вместо "crm.txt" использовал-бы __DIR__.'/crm.txt'
на всякий случай,) хоть и обычно не бывает разрешено создавать файлы где попало
0
04.10.2020, 01:07
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.10.2020, 01:07
Помогаю со студенческими работами здесь

Наличие строки в файле
Подскажите, как организовать проверку на наличие символов в файле. Нужно для подсчета количества...

Проверка на наличие строки в БД
Пытаюсь проверить, есть ли уже строка с такими же данными в БД(MySQL). При использовании...

Считать из файла с последующей записью в другой файл
не хочется слишком активно злоупотреблять вниманием и добротой обитателей форума, но никак не...

Проверка строки на наличие цифр
Написал код, который проверяет каждый элемент строки при помощи isdigit и если это цифра выводи...

Проверка на наличие строки в таблице
Есть таблица с эл. почтами, мне нужно проверить, есть ли в ней запись с нужным мылом, если есть,...

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru