URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 2204
[ Назад ]

Исходное сообщение
"Как удалить строку из текстовика, не переписывая его заново???"

Отправлено CRAY , 26-Окт-03 01:08 
Есть текстовый файл. Как на Perl удалить или изменить строку из его середины???
Так, чтобы не читать его полностью в массив и потом после удаления/изменения строки писать заново.

Содержание

Сообщения в этом обсуждении
"Как удалить строку из текстовика, не переписывая его заново?..."
Отправлено Михаил , 26-Окт-03 12:05 
>Есть текстовый файл. Как на Perl удалить или изменить строку из его
>середины???
>Так, чтобы не читать его полностью в массив и потом после удаления/изменения
>строки писать заново.
а положение строки в байтах от начала файла известно?
если да, то отпозиционироваться на нужное место и записать, а если нет, то куда писать?



"Как удалить строку из текстовика, не переписывая его заново?..."
Отправлено CRAY , 26-Окт-03 13:20 
>>Есть текстовый файл. Как на Perl удалить или изменить строку из его
>>середины???
>>Так, чтобы не читать его полностью в массив и потом после удаления/изменения
>>строки писать заново.
>а положение строки в байтах от начала файла известно?
>если да, то отпозиционироваться на нужное место и записать, а если нет,
>то куда писать?

Положение-то известно, но как удалить строку, чтобы следующая оказалась на ее месте и т.д. (чтоб они "подвинулись"), пример:

Исходный файл:
.............
строка1 данные1
строка2 данные2
строка3 данные3
строка4 данные4

Измененный файл:
.............
строка1 данные1
строка2 данные2
строка4 данные4


"Как удалить строку из текстовика, не переписывая его заново?..."
Отправлено devnull , 26-Окт-03 14:03 
>Положение-то известно, но как удалить строку, чтобы следующая оказалась на ее месте
>и т.д. (чтоб они "подвинулись"), пример:
>
>Исходный файл:
>.............
>строка1 данные1
>строка2 данные2
>строка3 данные3
>строка4 данные4
>
>Измененный файл:
>.............
>строка1 данные1
>строка2 данные2
>строка4 данные4

open RFILE,"<file.txt";
open WFILE,">wfile.txt";
while (<RFILE>){
       unless (/данные3/){
           print WFILE;
       }
}
close WFILE;
close RFILE;
rename wfile.txt file.txt;

а читать весь файл наверное все равно придется, но если файл 500 мегов, то не целиком а по строчкам.


"Как удалить строку из текстовика, не переписывая его заново?..."
Отправлено CRAY , 26-Окт-03 14:11 
Не знаешь как не читая...???

"Как удалить строку из текстовика, не переписывая его заново?..."
Отправлено CRAY , 26-Окт-03 14:11 
>open RFILE,"<file.txt";
>open WFILE,">wfile.txt";
>while (<RFILE>){
>       unless (/данные3/){
>           print
>WFILE;
>       }
>}
>close WFILE;
>close RFILE;
>rename wfile.txt file.txt;
>
>а читать весь файл наверное все равно придется, но если файл 500
>мегов, то не целиком а по строчкам.


Это все и так понятно... Но файл очень не хочицца целиком читать - он может быть и 500 мегов. Не знаешь как не читая...???


"Как удалить строку из текстовика, не переписывая его заново?..."
Отправлено devnull , 26-Окт-03 16:24 
>Это все и так понятно... Но файл очень не хочицца целиком читать
>- он может быть и 500 мегов. Не знаешь как не
>читая...???

это было бы и мне самому интересно. Как ты это себе представляешь? взять то, незнаю что, вырезать из незнаю что строчку, для всего остального файла изменить смещение (offset) каждой строчки....

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

открой любой файл например в hexeditor'e - ты можешь любую строку затереть нулями например,но структура то файла останется тойже. По этому смещению в файле что-то будет записано все равно.

поищи для себя подходящее из Perl Cookbook (в интренете нашел)

As explained ..., the operating system treats files as unstructured streams of bytes. This makes it impossible to insert, modify, or change bits of the file in place. (Except for the special case of fixed-record-length files) You can use a temporary file to hold the changed output, or you can read the entire file into memory, change it, and write it back out again.

Reading everything into memory is fine for small files, but doesn't scale well. Trying it on your 800 MB web server log files will either deplete your virtual memory or thrash your machine's VM system. For small files, though, this works:

open(F, "+<", $infile)      or die "can't read $infile: $!";
$out = "";
while (<F>) {
    s/DATE/localtime/eg;
    $out .= $_;
}
seek(F, 0, 0)               or die "can't seek to start of $infile: $!";
print F $out                or die "can't print to $infile: $!";
truncate(F, tell(F))        or die "can't truncate $infile: $!";
close(F)                    or die "can't close $infile: $!";


"Как удалить строку из текстовика, не переписывая его заново?..."
Отправлено Михаил , 26-Окт-03 18:50 
>Это все и так понятно... Но файл очень не хочицца целиком читать
>- он может быть и 500 мегов.

имхо, при таких масштабах уже СУБД нужна!
или хотя бы простейшая эмуляция с метками для строк, типа есть данные/нет данных...


"Как удалить строку из текстовика, не переписывая его заново?..."
Отправлено CRAY , 26-Окт-03 21:25 
Всем спасибо.

"Как удалить строку из текстовика, не переписывая его заново?..."
Отправлено CRAY , 26-Окт-03 21:26 
Так, фсе ясно!!
Я понял, что файл придется читать построчно, а потом, после модификации писать заново...

Фсем спасибо за ответы 8)


"Как удалить строку из текстовика, не переписывая его заново?..."
Отправлено devnull , 26-Окт-03 22:29 
>Так, фсе ясно!!
>Я понял, что файл придется читать построчно, а потом, после модификации писать
>заново...

1) читать-изменять-писать
или
2) читать строчку-писать строчку

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



"Как удалить строку из текстовика, не переписывая его заново?..."
Отправлено CRAY , 27-Окт-03 01:12 
Спасиба.
Еще вот одна темка.. http://www.opennet.me/openforum/vsluhforumID8/1832.html - глянь, может сталкивался?

"Как удалить строку из текстовика, не переписывая его заново?..."
Отправлено devnull , 28-Окт-03 20:27 
Tie::File - Access the lines of a disk file via a Perl array.

Tie::File represents a regular text file as a Perl array. Each element in the array corresponds to a record in the file. The first line of the file is element 0 of the array; the second line is element 1, and so on.

The file is not loaded into memory, so this will work even for gigantic files.

Changes to the array are reflected in the file immediately.

Lazy people and beginners may now stop reading the manual.