| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Perl: Системное программирование > Как удалить первую строку в файле? |
| Автор: Гость_Kris 18.11.2005, 13:27 |
| Сабж - если файл разросся до слишком больших размеров требуется удалить первую (соответственно самую старую) запись (строку). Вопрос- можно ли это сделать не переписывая данные в массив или во временный файл?? |
| Автор: arto 18.11.2005, 13:45 |
| нет |
| Автор: Kiber_rat 18.11.2005, 14:33 | ||
Вот пример... Массив не нужен, но временная переменная нужна
|
| Автор: korob2001 18.11.2005, 14:45 |
| А вообще это нужно изначально продумывать, ещё перед тем как файл разросся. Например держать в файле только последние 200 строк, всё остальные писать в архив. Допустим добавляется 201 строка, то первая выдёргивется и пишется в архив. Тогда можно и массивом воспользоваться. Кстати а строки какой длины? Может стоит подумать над тем что бы заюзать DBM? |
| Автор: Гость_Kris 18.11.2005, 16:03 | ||
| Почему-то не работает (после первой записи 4 байт данные в файл не добавляются) Строка запроса http://www.host-n-one.com/cgi-bin/form.cgi?b=%ff%ff%ff%f0
|
| Автор: Kiber_rat 18.11.2005, 19:15 |
| А можно узнать что ты пытаешься сделать? Кроме того, почему не пользуешься модулем CGI? Пример который я писал годится для строк, а тебе, похоже, нужно побайтово работать, тогда используй seek что бы задать позицию с которой нужно читать. Вобщем опиши задачу, тогда будет легче написать пример. |
| Автор: Гость_Kris 18.11.2005, 20:40 | ||
| Да собственно нужен такой массив каждый элемент в котором это четырехбайтовое число. Массив хранится в файле и при достижении некоторого числа элементов, скажем 1000, самая старая (первая) запись просто стирается, а новая добавляется в конец этого массива. Ну еще желательно проверять перед записью наличие элемента с таким значением в массиве-если имеется, то ничего не записываем и выходим. Странно, но проверка вроде-бы работает, несмотря на то что строки файла собственно и не строки, а четырехбайтные числа.... Передаем число на сервер -> http://www.host-n-one.com/cgi-bin/form.cgi?record=%ff%12%21%ff
А вот убрать первую запись (если число элементов > n) из файла не получается Я в Perl совсем зеленый , не знаю что в нем является строкой - m-байтная двоичная последовательность это строка? Или строка должна иметь какой-то символ ограничитель? Какая минимальная длина строки? Максимальная? Может ли строка содержать любые символы от 00 до FF или нет? |
| Автор: sharq 19.11.2005, 00:07 | ||
| Строка - это все что в кавычках двойных или одинаковых, число может использоваться тоже как строка, все зависит от контекста. Perl сам определяет строка здесь или число. Никаких ограничителей у строки нет, только - размер оперативной памяти. Минимальная длина строки - длина пустой строки = 0.
да, строка может содержать все что угодно, на то она и строка. |
| Автор: korob2001 19.11.2005, 00:28 | ||
| Файл открывай как для чтения, так и для записи. Читай блоками байтов, а не строками. Вот тебе пример c коментариями. Только в данном случае параметр получаем из командной строки, это я сделал для более легкого тестирования.
Только +< не создаёт файла, потому тебе нужно будет создать, пустой, файл самому. Затем настрой первые 3 переменные. Из командной строки передавай параметр: C:\>perl test.pl ffff C:\>perl test.pl xxxx C:\>perl test.pl aaaa И так далее. В файле будет сохранено максимум $max_block блоков, если если блоков больше или равно, то первая запись будет удалена, а новая запись будет добавлена в конец. Если переданный параметр уже есть, то он не будет сохранён повторно. Я не блокировал файл, но в конечной программе это нужно будет сделать. Не знаю это то, что тебе нужно или нет. Вобщем пробуй. Если что-то будет не ясно, пиши. |
| Автор: Kiber_rat 19.11.2005, 02:53 | ||
| По порядку. Строкой, при чтении из файла по крайней мере, считается последовательность символов ограниченная символом перевода строки (\n). Далее, то что ты хочешь хранить в этом файле? Я так понимаю что это двоичные данные? А насколько критично их писать не на одной строке? Добавляй перевод строки и все будет работать. А еще лучше хранить это в dbm файле. Доступ будет проще и быстрее. И используй модуль CGI, он тебе сильно жизнь облегчит. Да и массив тебе ничем не мешает, скорее наоборот
Проверь, может подойдет P.S. Увидел ответы после того как написал |
| Автор: Kiber_rat 19.11.2005, 03:40 | ||
Вот, еще один вариант, так сказать "компиляция советов"
|
| Автор: Guest 19.11.2005, 16:28 | ||
| Ураааа! Работает Не уверен насчет flock(), говорят это срабатывает не во всех случаях, еще не получилось открыть файл с ключом :raw - Unknown open mode! а в остальном вот наваял по вашим советам
|
| Автор: korob2001 20.11.2005, 08:28 | ||
Вообще-то, было бы не плохо проверять файл не только на существование, но так же и на то, что он является двоичным.
Но это уже тонкости. |
| Автор: Гость_Kris 20.11.2005, 11:16 | ||
| Еще выяснилось что паковать надо с флагом Н8, иначе данные сохраняются как строка символов. а не двоичное число Для оптимизации поиска ввел дополнительную переменную, чтобы не распаковывать в цикле.
|
| Автор: korob2001 20.11.2005, 23:14 |
| a - Строка байт, дополняемая нулями H - Шестнадцатиричная строка, старший полубайт впереди. |
| Автор: Guest 21.11.2005, 13:44 | ||
| Добавил еще переменную (она же флаг). Теперь можно не только добавить строчку, но и удалить и модифицировать любую строку Интересно, а можно сделатьтак чтобы одномоментно выполнялась только одна копия процесса? Может ли сервак поставить запрос к скрипту в очередь?
|
| Автор: korob2001 21.11.2005, 22:53 | ||
Создай блокировку на другой файл, пусть на нём и создаётся очередь. Например:
Теперь сохрани всё это дело и попробуй запустить из командной строки. Запусти второй сеанс командной строки и запусти тот же файл. После в одном ты видишь запрос на ввод имени, во втором ничего, так как ожидает в очереди. Теперь в первом введи своё имя и нажми enter, в первом ты увидешь приветствие, а во втором появится запрос на вод имени, так как подошла его очередь. Получается мы блокируем часть кода. Всё что находится между вызовами подпрограмм start_lock() и stop_lock() будет забокированно. Очередь создаётся в том месте, где была вызвана подпрограмма start_lock(). |
| Автор: Гость_Kris 22.11.2005, 14:28 | ||
| А зачем здесь использовать модуль Fcntl? Вот такой код тоже вроде нормально работает
|
| Автор: korob2001 22.11.2005, 15:03 |
| Ну это уже дело вкуса, лично я пользуюсь всегда Fcntl, тем более он входит в стандартыный пакет. Смысл был не в Fcntl, а в том как создать очередь с помощью блокировки. |