Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Системное программирование > Работа с файлом в Perl


Автор: C.Smoke 12.2.2005, 11:22
Доброго времени суток!

Проблема в следующем:
Есть фаил "ITEMS.txt"
в нём записаны данные вида:
"#001::100::90::text
#002::65::75::text2
... и т.д."

как на Perl заменить одну строку на другую.
например :
"#002::65::75::text2" на "#002::64::75::text2"
без её смещения в тексте.

возможно ли такое. и если есть в Perl функция которая очищает фаил перед открытием немогли бы вы про неё рассказать.

Зарание Спасибо!

smile

Автор: dimes 12.2.2005, 12:54
Цитата(C @ 12.2.2005, 12:22)
и если есть в Perl функция которая очищает фаил перед открытием немогли бы вы про неё рассказать.

Есть такая функция! Замечательная функция! И в любой документации нормально описаная.

Открывает файл для записи если нет файла, создаст, если есть очистит
open(FIL,">file.txt");

Открывает файл для четения и записи если нет файла, создаст, если есть очистит
open(FIL,"+>file.txt");


Цитата(C @ 12.2.2005, 12:22)
как на Perl заменить одну строку на другую. без её смещения в тексте.

А никак, понятие строки ввели люди для удобства а в файле нет никаких строк, но можно проблемму решить так:

1. Загрузить файл в память, там его отредактировать а потом сохранить
+ очень просто
- может памяти не хватить
- следит чтобы другие процессы не могли править этот файл, но это легко решается.
2. В процессе прочтения файла создавать копию исходного файла с отредактироваными строками а потом копией заменить оригенал.
+ Нужно мало памяти
+ Строки легко удаляются
+ Файл занимает ровно столько сколько он содержит инфы + некая служебная инфа
- Нужно больше памяти на винте (ерунда конечно но всетаки...)
- много не нужный действий, если в файле 1000 строк а нужно отредактировать 10 то оставшиеся 990 строк всеравно придется копировать.
- Немного труднее лочить файл для других процессов
3. Создать файл с фиксированными размером поля, т.е. всегда считать что строка не может быть больше или меньше указанного размера. Если меньше то добивать до указанного размера, если больше то усекать.
+ меньше операции, по сравнению с 2
+ проще лочить файл
+ нужно не много памяти
- задача не тривеальная, не для новичка
- нужно больше места не винте для файла
- теряется инфа в строке каторая не влезла в строку
- если меняется размер строки, нужно будет пересоздать файл
- появление дыр в файле из-за удаления строк

Автор: C.Smoke 12.2.2005, 13:24
Цитата
1. Загрузить файл в память, там его отредактировать а потом сохранить
+ очень просто
- может памяти не хватить
- следит чтобы другие процессы не могли править этот файл, но это легко решается.


А сколько выделяется памяти?
у меня в файле 300-500 строк
по ~30 символов. (9000-15000символов в файле)
хватит ли памяти на такой фаил!?
подойдёт ли такой код:
Код

open(BASE,"+>ITEMS.txt");
@base=<BASE>;
foreach $str (@base)
{
               # какие то действия с данными
print (BASE,"$id::$col::$cen::$nam\n"); #запись данных обратно в фаил
}
close(BASE);


насколько медленный этот способ?
Заранее спасибо smile

Автор: dimes 12.2.2005, 13:39
Цитата(C @ 12.2.2005, 14:24)
А сколько выделяется памяти?
у меня в файле 300-500 строк
по ~30 символов. (9000-15000символов в файле)
хватит ли памяти на такой фаил!?

Не знаю. 15 немного но если завтра станет 1.5М? Или если он(скрипт) дергается 20 раз в сек? Или ты уже загрузил 2М. Самое точное нам скажет опыт smile


Цитата(C @ 12.2.2005, 14:24)
open(BASE,"+>ITEMS.txt");
@base=<BASE>;

Конструкиция бессмысленна, потому что
Цитата(dimes @ 12.2.2005, 13:54)
Открывает файл для четения и записи если нет файла, создаст, если есть очистит

Т.е. ты гарантированно читаеш пустой файл.


Цитата(C @ 12.2.2005, 14:24)
foreach $str (@base)
{
# какие то действия с данными
print (BASE,"$id::$col::$cen::$nam\n"); #запись данных обратно в фаил
}

Так как ты читаеш пустой файл то это не будет ошибки, но если ты хочеш работать с уже наполенным файлом, то забыл 2 комманды.

Код

seek(BASE,0,0); # Поставит указатель в начало файла, ты же дочитал его до конца.
truncate(BASE,0); # Урежит файл в 0 чтобы небыло хвостов.
# Если дальше пойдет что то не так то ты потеряеш все данные!!!
foreach $str (@base)
{
# какие то действия с данными
print (BASE,"$id::$col::$cen::$nam\n"); #запись данных обратно в фаил
}


Так же пропущенна команда flock, как ты будеш отслеживать одновременный доступ к файлу от разных клиентов?

Автор: C.Smoke 12.2.2005, 15:32
Огромное спасибо!
Всё работает! smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)