найти и заменить значения в плоском файле с помощью PHP

Я думал, что уже был вопрос по этому поводу, но я не могу его найти. Возможно, решение слишком простое... Во всяком случае, у меня есть плоский файл, и я хочу, чтобы пользователь мог изменять значения на основе имени. Я уже разобрался с созданием новых пар имя+значение, используя режим fopen('a'), используя jQuery для отправки вызова AJAX с newValue и newName. Но скажем, содержимое выглядит так:

host|http:www.stackoverflow.com
folder|/questions/
folder2|/users/

И теперь я хочу изменить значение folder. Итак, я отправлю folder как oldName, а /tags/ как newValue. Каков наилучший способ перезаписать значение? Порядок в списке не имеет значения, имя всегда будет слева, за ним следует | (вертикальная черта), значение и затем new-line.

Моей первой мыслью было прочитать список, сохранить его в массиве, найти во всех [0] oldName, затем изменить принадлежащий ему [1], а затем записать его обратно в файл. Но я чувствую, что есть лучший способ обойти это? Есть идеи? Может быть, regex?


person peirix    schedule 31.05.2010    source источник
comment
Не забудьте какой-нибудь запорный механизм. Неизбежны проблемы, если 2 скрипта редактируют файл одновременно.   -  person extraneon    schedule 31.05.2010
comment
CSV — это аббревиатура для значений, разделенных запятыми, и ваш разделитель — это вертикальная черта, а не запятая. Хотя многие импортеры CSV позволяют вам установить в качестве разделителя что-то, что не является запятой, я бы все же сказал, что лучше называть это плоским файлом. en.wikipedia.org/wiki/Flat_file_database   -  person HostileFork says dont trust SE    schedule 31.05.2010
comment
@extraneon Да, это только для администраторов. И будет один файл на одного администратора. Но я посмотрю на механизмы блокировки, просто на всякий случай (: спасибо, что напомнили мне. @Hostile Fork, да, я знаю, но на самом деле между ними нет никакой практической разницы, не так ли?   -  person peirix    schedule 31.05.2010
comment
Когда я использую слово, Шалтай-Болтай говорит довольно презрительным тоном. Оно означает именно то, что я выбираю, ни больше, ни меньше. -- Вопрос в том, -- сказала Алиса, -- можно ли заставить слова означать так много разных вещей. :) Точный выбор нашей терминологии позволяет избежать путаницы и помогает в соответствующей маркировке.   -  person HostileFork says dont trust SE    schedule 31.05.2010
comment
@Hostile Fork (: Нет ничего лучше, чем цитировать Льюиса Кэрролла, чтобы понять смысл семантики. Точка зрения принята.   -  person peirix    schedule 31.05.2010
comment
Я не программист PHP (по своему выбору), но поиск в плоском файле PHP выдает несколько вещей, которые могут быть или не быть полезными, если вы ищете API-интерфейсы, ориентированные на базу данных, а не более целесообразный хак...!   -  person HostileFork says dont trust SE    schedule 31.05.2010


Ответы (2)


Очень простым способом было бы использовать str_replace() для всего файла:

// read the file
$file = file_get_contents('filename.csv');
// replace the data
$file = str_replace('folder|oldValue', 'folder|newValue', $file);
// write the file
file_put_contents('filename.csv', $file);

Это должно работать только с одним пользователем файла за раз. Но база данных всегда лучше. Если вам нужен CSV, лучше иметь дополнительный скрипт DB to CSV, чем только файл CSV.

person 2ndkauboy    schedule 31.05.2010

Вы можете хранить список в памяти, используя функцию PHP, такую ​​​​как APC, и время от времени записывать его на диск. Таким образом, вы читаете его только тогда, когда его нет в памяти.

Если вы хотите ориентироваться на производительность, хранение этой информации в CSV, вероятно, не самое лучшее для начала. Если вы не хотите использовать настоящую RDMS (MySQL), я бы предложил использовать SQLite. Он предоставляет все функции, которые вы ищете (ОБНОВЛЕНИЕ) в этом случае, и он действует точно так же, как CSV в том смысле, что это просто файл на вашем жестком диске и не имеет параллелизма.

Если это не вариант, другим способом является использование команд уровня оболочки, таких как sed и awk, для выполнения встроенных изменений регулярных выражений. Наконец, чтение всего файла в строку, выполнение противной настройки регулярного выражения для него (s///), а затем запись его снова сработает.

person Matt S    schedule 31.05.2010
comment
Производительность не проблема, на самом деле. Максимум в файле может быть 5 строк, поэтому я не буду заморачиваться с MySQL. Но будет один файл для каждого клиента/пользователя. Однако я посмотрю на SQLite. Спасибо. - person peirix; 31.05.2010