Модераторы: ginnie, korob2001

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как удалить первую строку в файле? 
:(
    Опции темы
Гость_Kris
Дата 18.11.2005, 13:27 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Сабж - если файл разросся до слишком больших размеров требуется удалить первую
(соответственно самую старую) запись (строку).
Вопрос- можно ли это сделать не переписывая данные в массив или во временный файл?? smile
  Вверх
arto
Дата 18.11.2005, 13:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1495
Регистрация: 31.10.2004

Репутация: 1
Всего: 40



нет
PM MAIL ICQ   Вверх
Kiber_rat
Дата 18.11.2005, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MACMANIAC
**


Профиль
Группа: Участник
Сообщений: 276
Регистрация: 18.4.2002
Где: Ashdod, Israel

Репутация: нет
Всего: 9



Вот пример... Массив не нужен, но временная переменная нужна smile
Код

#!/usr/bin/perl
use strict;
use warnings;
my $counter=0;
my $buf='';
open FD,"<testfile" or die;
while (<FD>){
    # переписав условие можно удалять сколько угодно строк от начала файла.
    $buf.=$_ if $counter++; 

close FD; 
open FD, ">testfile" or die;
print FD $buf;



--------------------
Best regards!                                                             
@..@_____Ku6ep
=*=______\______KPbIC
Код
print join "",map{chr}(split/(\w{2})/,hex(int(2175.57302796298**2)))
PM WWW ICQ Skype Jabber YIM   Вверх
korob2001
Дата 18.11.2005, 14:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 6
Всего: 61



А вообще это нужно изначально продумывать, ещё перед тем как файл разросся. Например держать в файле только последние 200 строк, всё остальные писать в архив. Допустим добавляется 201 строка, то первая выдёргивется и пишется в архив. Тогда можно и массивом воспользоваться. Кстати а строки какой длины? Может стоит подумать над тем что бы заюзать DBM?


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Гость_Kris
Дата 18.11.2005, 16:03 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Почему-то не работает (после первой записи 4 байт данные в файл не добавляются) smile
Строка запроса
http://www.host-n-one.com/cgi-bin/form.cgi?b=%ff%ff%ff%f0

Код

#!/usr/bin/perl

$counter=0;
$buf='';
$size=0;

#Get data --------
if ($ENV{'REQUEST_METHOD'} eq "POST")
    {
      read(STDIN, $bufer, $ENV{'CONTENT_LENGTH'});
    }
else
    {
      $bufer=$ENV{'QUERY_STRING'};
    }    

@pairs = split(/&/, $bufer);
foreach $pair (@pairs) {
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
   $VOTE{$name} = $value;
}

$path="$ENV{'DOCUMENT_ROOT'}";
$filename=$path."/output/test.txt";
     
#See if file already exists --------

$test=0; 
if (-e("$filename")){ $size= -s $filename; }
else { $test=1;  } 

#If exists check it for duplicates --------

if ($test==0) {
open (NAMEFILE, "$filename");
 while(<NAMEFILE>)
{
 if (/$value/) { $test=0; break; }
}
close (NAMEFILE);
}
 
#If no duplicates found --------

if ($test==1)  {
#If file is too large delete first 4 bytes --------

if ($size>=12)  { 
open (NAMEFILE, "$filename"); 
sysread(NAMEFILE, &buf, $size-4, 4); 

close (NAMEFILE);
open (NAMEFILE, ">$filename"); 
flock (NAMEFILE, 2);
syswrite (NAMEFILE, $buf, $size-4, 0);
close (NAMEFILE);
$size-=4;
}
#Add new record --------

open (NAMEFILE, ">>$filename"); 
flock (NAMEFILE, 2);
print NAMEFILE $value;
close (NAMEFILE);
$size+=4;
}



  Вверх
Kiber_rat
Дата 18.11.2005, 19:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MACMANIAC
**


Профиль
Группа: Участник
Сообщений: 276
Регистрация: 18.4.2002
Где: Ashdod, Israel

Репутация: нет
Всего: 9



А можно узнать что ты пытаешься сделать? Кроме того, почему не пользуешься модулем CGI? Пример который я писал годится для строк, а тебе, похоже, нужно побайтово работать, тогда используй seek что бы задать позицию с которой нужно читать. Вобщем опиши задачу, тогда будет легче написать пример.


--------------------
Best regards!                                                             
@..@_____Ku6ep
=*=______\______KPbIC
Код
print join "",map{chr}(split/(\w{2})/,hex(int(2175.57302796298**2)))
PM WWW ICQ Skype Jabber YIM   Вверх
Гость_Kris
Дата 18.11.2005, 20:40 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Да собственно нужен такой массив каждый элемент в котором это четырехбайтовое число.
Массив хранится в файле и при достижении некоторого числа элементов, скажем 1000, самая старая (первая) запись просто стирается, а новая добавляется в конец этого массива.
Ну еще желательно проверять перед записью наличие элемента с таким значением в массиве-если имеется, то ничего не записываем и выходим.

Странно, но проверка вроде-бы работает, несмотря на то что строки файла собственно и не строки, а четырехбайтные числа....
Передаем число на сервер -> http://www.host-n-one.com/cgi-bin/form.cgi...rd=%ff%12%21%ff
Код

$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
#$value=0xff1221ff;
#проверяем может такое уже есть....
open (NAMEFILE, "$filename");
 while(<NAMEFILE>)
{
 if (/$value/) { $bTest=0; break; }
}
close (NAMEFILE);



А вот убрать первую запись (если число элементов > n) из файла не получается smile

Я в Perl совсем зеленый , не знаю что в нем является строкой - m-байтная двоичная последовательность это строка? Или строка должна иметь какой-то символ ограничитель?
Какая минимальная длина строки? Максимальная? Может ли строка содержать любые символы от 00 до FF или нет?

  Вверх
sharq
Дата 19.11.2005, 00:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Perl Liker
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 13.12.2004
Где: Ростов-на-Дону

Репутация: 3
Всего: 28



Строка - это все что в кавычках двойных или одинаковых, число может использоваться тоже как строка, все зависит от контекста. Perl сам определяет строка здесь или число.
Никаких ограничителей у строки нет, только - размер оперативной памяти. smile
Минимальная длина строки - длина пустой строки = 0.

Цитата
Может ли строка содержать любые символы от 00 до FF или нет?

да, строка может содержать все что угодно, на то она и строка.

smile

Это сообщение отредактировал(а) sharq - 19.11.2005, 00:08


--------------------
[color=gray]There's More Than One Way To Do It[/color]
PM MAIL WWW ICQ Skype   Вверх
korob2001
Дата 19.11.2005, 00:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 6
Всего: 61



Файл открывай как для чтения, так и для записи. Читай блоками байтов, а не строками. Вот тебе пример c коментариями.
Только в данном случае параметр получаем из командной строки, это я сделал для более легкого тестирования.
Код

#!/usr/bin/perl -w
use strict;

# Имя файла, с которым будем работать
my $file = "test.txt";
# Получаем рараметр из командной строки
chomp(my $param = shift);
# Флаг, по нему будем определять есть ли такая строка в файле
my $flag = 0;
# Максимальное кол-во блоков, т.е. записей в файле
my $max_block = 5;
# Длана блока в байтах
my $block_length = 4;
my @bytes = ();
my $buff;

# Отарываем файл для чтения и записи
open(F, "+< $file") or die "Can't open file: $!\n";

# Следующая строка нужна только для винды, но под
# никсами она ничего не делает потому указываем её
# в любом случае для переносимости
binmode F;

# Можно было этого и не делать, переходим в начало файла
seek(F, 0, 0);

# Читаем файл блоками по $block_length байт
while ( read( F, $buff, $block_length ) ) {
        # Распаковуем полученные байты в строку и
        # сравниваем её с полученной из командной строки
        if ( unpack("a$block_length",$buff) eq $param ) {
             # Если оказались здесь, значит такая запись есть в файле
             # устанавливаем флаг и завершаем цикл, как я понял делать
             # в этом случае ничего не нужно
             $flag = 1;
             last;
        }
        # Сохраняем в массив полученный блок
        push(@bytes, $buff);
}

# Проверяем был ли установлен флаг, если нет то:
unless ( $flag ) {
      # переходим в начало файла если текущая позиция / $block_length больше $max_block
      if ((tell() / $block_length) >= $max_block ) {
           seek(F,0,0);  # Переходим в начало
           # Удаляем первый элемент
           shift @bytes;
           # Добавляем новый в конец, перед этим упакуем его
           push(@bytes, pack("a$block_length", $param));
           # Перезаписываем файл
           print F $_ while ($_ = shift @bytes);
      } else {
            # Упакуем строку и добавим в файл
            print F pack("a$block_length", "$param");
      }
}

close(F);

Только +< не создаёт файла, потому тебе нужно будет создать, пустой, файл самому. Затем настрой первые 3 переменные. Из командной строки передавай параметр:
C:\>perl test.pl ffff
C:\>perl test.pl xxxx
C:\>perl test.pl aaaa
И так далее.
В файле будет сохранено максимум $max_block блоков, если если блоков больше или равно, то первая запись будет удалена, а новая запись будет добавлена в конец.
Если переданный параметр уже есть, то он не будет сохранён повторно.
Я не блокировал файл, но в конечной программе это нужно будет сделать.

Не знаю это то, что тебе нужно или нет. Вобщем пробуй. Если что-то будет не ясно, пиши.

Это сообщение отредактировал(а) korob2001 - 19.11.2005, 02:41


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Kiber_rat
Дата 19.11.2005, 02:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MACMANIAC
**


Профиль
Группа: Участник
Сообщений: 276
Регистрация: 18.4.2002
Где: Ashdod, Israel

Репутация: нет
Всего: 9



По порядку. Строкой, при чтении из файла по крайней мере, считается последовательность символов ограниченная символом перевода строки (\n). Далее, то что ты хочешь хранить в этом файле? Я так понимаю что это двоичные данные?
А насколько критично их писать не на одной строке? Добавляй перевод строки и все будет работать. А еще лучше хранить это в dbm файле. Доступ будет проще и быстрее. И используй модуль CGI, он тебе сильно жизнь облегчит. Да и массив тебе ничем не мешает, скорее наоборот smile
Код

#!/usr/bin/perl
#Crafted by Ku6ep :)
use strict;
use warnings;
use CGI;
my %Q = CGI::Vars();
my $LIMIT=10; # макс. кол-во элементов
my @buf;
my $file = 'data/outfile';
print CGI::header();
die "Don't get variable!\n" unless $Q{value}; # Умереть если не передана value
if (-e $file){
    open FR,"<$file" or die "Can't open file, $!";
    while (<FR>) {
        chomp;
        push (@buf,$_);
        if (/^$Q{value}/) {
            print "Data exists!";
            exit; 
        }
    }
    shift @buf if @buf >= $LIMIT;
}
push(@buf, $Q{value}); 
open FO,">$file" or die "Can't open file, $!";
print FO "$_\n" for @buf; # Добавляем перевод строки к каждой записи
close FO;
print "Data added...";

Проверь, может подойдет smile
P.S. Увидел ответы после того как написал smile Так что у тебя теперь есть из чего составить нужный тебе скрипт...


--------------------
Best regards!                                                             
@..@_____Ku6ep
=*=______\______KPbIC
Код
print join "",map{chr}(split/(\w{2})/,hex(int(2175.57302796298**2)))
PM WWW ICQ Skype Jabber YIM   Вверх
Kiber_rat
Дата 19.11.2005, 03:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MACMANIAC
**


Профиль
Группа: Участник
Сообщений: 276
Регистрация: 18.4.2002
Где: Ashdod, Israel

Репутация: нет
Всего: 9



Вот, еще один вариант, так сказать "компиляция советов" smile
Код

#!/usr/bin/perl
use strict;
use warnings;
use CGI;
my %Q = CGI::Vars();
die "Don't get variable!\n" unless $Q{value}; # Умереть если не передана value
my $LIMIT=10; # макс. кол-во элементов
my $datalengh=4; # длина одной записи
my (@buf, $buff);
my $file = 'data/outfile_bin';
print CGI::header();
if (!-e $file) { # Создать файл если не было...
    open FH, "> :raw",$file;
    print FH pack("a$datalengh",$Q{value}); # ...записать в него данные...
    close FH;
    print "Data added...";
    exit; #... и выйти
}
open FH, "+< :raw",$file or die "Can't open file, $!"; # :raw - вместо binmode :)
while (read(FH,$buff,$datalengh)) {
    if (unpack("a$datalengh",$buff) eq $Q{value}) {
        print "Data exists!";
        exit;
    }
    push (@buf,$buff);
}
shift @buf if @buf >= $LIMIT;
push(@buf, pack("a$datalengh",$Q{value}));
seek(FH,0,0);
print FH for @buf;
close FH;
print "Data added...";



--------------------
Best regards!                                                             
@..@_____Ku6ep
=*=______\______KPbIC
Код
print join "",map{chr}(split/(\w{2})/,hex(int(2175.57302796298**2)))
PM WWW ICQ Skype Jabber YIM   Вверх
Guest
Дата 19.11.2005, 16:28 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Ураааа! Работает smile Пасибо огромное всем за помощь!
Не уверен насчет flock(), говорят это срабатывает не во всех случаях,
еще не получилось открыть файл с ключом :raw - Unknown open mode!
а в остальном вот наваял по вашим советамsmile

Код

#!/usr/bin/perl
use strict;
#use warnings;

my $value = shift(@ARGV); # берет командную строку

my $LIMIT=10; # макс. кол-во элементов
my $datalengh=4; # длина одной записи
my (@buf, $buff);
my $file="test.txt";
my $flag = 0;


if (!-e $file) { # Создать файл если не было...
    open FH, ">$file";
    binmode FH;
    print FH pack("a$datalengh",$value);     # записать в него данные...
    close (FH);
    #print "Data added...";
    exit(0); 
}

# Отkрываем файл для чтения и записи
 open FH, "+<$file";        # Unknown open mode!!! if open FH, "+< :raw"; вместо binmode :)
 flock (FH, 2);
 binmode FH;
 seek(FH, 0, 0);

# Читаем файл блоками по $block_length байт
 while (read(FH,$buff,$datalengh)) {
    if (unpack("a$datalengh",$buff) eq $value) {
        #print "Data exists!";
        #exit;
       $flag = 1;
       last;
    }
    push (@buf,$buff);    # Сохраняем в массив полученный блок    
}

# Проверяем был ли установлен флаг, если нет то:
unless ( $flag ) {
shift @buf if @buf >= $LIMIT;
push(@buf, pack("a$datalengh",$value));
seek(FH,0,0);
print FH for @buf;
}
flock (FH, 0);
close FH;


  Вверх
korob2001
Дата 20.11.2005, 08:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 6
Всего: 61



Вообще-то, было бы не плохо проверять файл не только на существование, но так же и на то, что он является двоичным.
Код

# Удаляем файл если он существует и не является двоичным
unlink $file if ( (-e $file) and (!-B $file) );
unless ( -e $file ) {
              # Файл не существует
} else {
              # Существует, а так же он двоичный
}

Но это уже тонкости. smile


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Гость_Kris
Дата 20.11.2005, 11:16 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Еще выяснилось что паковать надо с флагом Н8, иначе данные сохраняются как строка символов. а не двоичное числоsmile
Для оптимизации поиска ввел дополнительную переменную, чтобы не распаковывать в цикле.

Код

my $bin_a=pack("H8",$value);
####################

 while (read(FH,$buff,$datalengh)) {

    if ($buff eq $bin_a) {
       $flag = 1;
       last;
    }
    push (@buf,$buff);    
}

  Вверх
korob2001
Дата 20.11.2005, 23:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 6
Всего: 61



a - Строка байт, дополняемая нулями
H - Шестнадцатиричная строка, старший полубайт впереди.


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl: Системное программирование"
korob2001
sharq
  • В этом разделе обсуждаются вопросы относящиеся только к системному программированию на Perl
  • Если ваш вопрос не относится к системному или CGI программированию, задавайте его в общем разделе
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0993 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.