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


Автор: d0k 19.3.2006, 18:35
Тема такова:
Открываем файл , считываем строки <filehandle>. Необходимо изменять положение текущей считываемой строки ( также положение текущей записи в файл). Переменная $. изменяется по порядку как и должна показывает номер строки. $/ не трогаю (по умолчанию). Но если я меняю $. , надеясь перейти на определенную строку, то просто $. изменяется, а указатель остаётся на том же месте и аккумулируется уже от мною заданного значения. Почему?
И всё-таки как изменить указатель строки?

Для понимания более точный вопрос :
Как перейти на последнию строку или как считать строку с заданным номером? smile

seek и tell - работают с байтами - это понятно, а нет ли чего похожего но для работы со строками? smile

Автор: BlackLFL 19.3.2006, 18:45
Цитата(d0k @ 19.3.2006, 19:35 Найти цитируемый пост)
seek и tell - работают с байтами - это понятно, а нет ли чего похожего но для работы со строками?

perldoc read
Цитата

    read FILEHANDLE,SCALAR,LENGTH,OFFSET
    read FILEHANDLE,SCALAR,LENGTH
            Attempts to read LENGTH *characters* of data into variable
            SCALAR from the specified FILEHANDLE. Returns the number of
            characters actually read, 0 at end of file, or undef if there
            was an error (in the latter case $! is also set). SCALAR will be
            grown or shrunk so that the last character actually read is the
            last character of the scalar after the read.

            An OFFSET may be specified to place the read data at some place
            in the string other than the beginning. A negative OFFSET
            specifies placement at that many characters counting backwards
            from the end of the string. A positive OFFSET greater than the
            length of SCALAR results in the string being padded to the
            required size with "\0" bytes before the result of the read is
            appended.

            The call is actually implemented in terms of either Perl's or
            system's fread() call. To get a true read(2) system call, see
            "sysread".

            Note the *characters*: depending on the status of the
            filehandle, either (8-bit) bytes or characters are read. By
            default all filehandles operate on bytes, but for example if the
            filehandle has been opened with the ":utf8" I/O layer (see
            "open", and the "open" pragma, open), the I/O will operate on
            UTF-8 encoded Unicode characters, not bytes. Similarly for the
            ":encoding" pragma: in that case pretty much any characters can
            be read.

Автор: nitr 19.3.2006, 18:47
если файлик маленький:

можно через массив
@content = <HANDLE>;
искомая строка $str = $content[NUMBER-1]; , начиная с 1 smile, если хоцца с нуля то просто [NUMBER]

Вот хорошее решение для любого размера и большая скорость -
http://search.cpan.org/author/MJD/Tie-File-0.96/lib/Tie/File.pm
Он занимаеться тем же smile Представляет файлик как массив smile
Код

use Tie::File;
use Fcntl;

tie @content, 'Tie::File', $file, mode => O_RDWR or die "Error - $!\n";
print "$content[NUMBER-1]\n";

и последняя строка: print "$content[-1]\n";

Для чего тебе это всё? Покажи кусок кода smile Вариантов немеренно. даже можно работать с файлом как БД =)

Вот по твоему вопросу:
Код

#!/usr/bin/perl -w
# ex.pl

$file = "ex.pl";
open HANDLE, "< $file";
while(<HANDLE>) {
  #что-то делаем
  last if $. == 4;
}
print;

результат $file = "ex.pl";

для последней:
Код

#!/usr/bin/perl -w
# ex.pl

$file = "ex.pl";
open HANDLE, "< $file";
while(<HANDLE>) {
  #что-то делаем
  last if eof;
}
print;

результат print;

Автор: BlackLFL 19.3.2006, 18:54
Цитата

Для чего тебе это всё? Покажи кусок кода  Вариантов немеренно. даже можно работать с файлом как БД =)

поддерживаю

Автор: d0k 19.3.2006, 20:53
Мне это нужно, чтобы просто к любому символу в любой строке текстового файла можно было обратиться.
Ещё поясню, прочитал (в perldoc),что изменяя переменную $. (в которой хранится номер текущей строки) можно обращаться к любой строке:
Код

open (FILEIO,"+>file");
while ($a=<FILEIO>){
print "$a   $."; # $. изменяется по порядку
}
$.=5;
$a=<FILEIO>;
print $a; #печатает пятую строку


Массив подходит - но не целесообразно после изменений в одной строке сохранять весь массив, особенно если он на 100000 строк.
Массив можно, но как тогда заменить в файле именно определённую строку,а не переписывать весь массив в файл заного.

nitr написал:
Код

file = "ex.pl";
open HANDLE, "< $file";
while(<HANDLE>) {
  #что-то делаем
  last if eof;
}
print;

Это верно - когда мы просто перебором доходим до последней строки, а дальше как вернуться вверх? Или начать перебор заного? А если в файле 100000 строк.
А как после того как мы прочитали последнию строку прочитать предпоследнию а затем 4-ую затем 8-ую 2-ую и т.д. в любой последовательности?

Автор: nitr 19.3.2006, 21:00
Цитата

если файлик маленький:

можно через массив
@content = <HANDLE>;
искомая строка $str = $content[NUMBER-1]; , начиная с 1 smile, если хоцца с нуля то просто [NUMBER]

Вот хорошее решение для любого размера и большая скорость -
http://search.cpan.org/author/MJD/Tie-File-0.96/lib/Tie/File.pm
Он занимаеться тем же smile Представляет файлик как массив smile
Код

use Tie::File;
use Fcntl;

tie @content, 'Tie::File', $file, mode => O_RDWR or die "Error - $!\n";
print "$content[NUMBER-1]\n";

и последняя строка: print "$content[-1]\n";


http://search.cpan.org/author/MJD/Tie-File-0.96/lib/Tie/File.pm ВНИМАТЕЛЬНО и для чего это smile Пользуйся им. Можно ещё и как с БД smile
Код

use DB_File;
use Fcntl;
$tie = tie(@content, DB_File, $file, O_RDWR, 0755, $DB_RECNO);
print $content[NUMBER-1];

Автор: nitr 19.3.2006, 21:21
один из самых простых подсчётов строк
Код

open HANDLE, "< $file";
for($lines=0; <HANDLE>; $lines++) {}

Автор: d0k 23.3.2006, 02:02
smile nitr спасибо
DB_File очень удобная библиотека в прямом смысле привязал хеш к файлу и никаких проблем. Berkeley DB рулят, но уж слишком заумно сделано.

ладно разберусь

Автор: Бонифаций 23.3.2006, 13:19
Цитата(d0k @ 19.3.2006, 20:53 Найти цитируемый пост)
Массив подходит - но не целесообразно после изменений в одной строке сохранять весь массив, особенно если он на 100000 строк.
Массив можно, но как тогда заменить в файле именно определённую строку,а не переписывать весь массив в файл заного.



Очень интересно. А как вы собираетесь изменить только одну строку в тестовом файле?. Вы полагаете текстовые редакторы не переписывают файлы если вы изменили только одну строку?

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