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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблемы с индексированием, Файл индекса искажает данные 
:(
    Опции темы
Uran34
Дата 18.11.2010, 19:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 9.11.2010

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



Помогите разобраться. Есть задача: в некотором файле file.txt хранятся данные
в виде текстовых строк. Необходимо, введя номер строки извлечь соответсвующую
ему строку. Процедура здесь вроде бы не сложная.  Используется индексирование.
В первой подпрограмме DAT открываем файл с текстом file.txt и через функцию tell получаем побайтовое смещение
каждой строки.Упаковываем их по шаблону "N" и Записываем в индексный файл
index.idx. Во второй подпрограмме INDX сначала определяем смещение в
индексе, соответсвующее номеру искомой строки, устанавливаем позицию seek для считывания
в index.idx и считываем в переменную $entry упакованное значение байтов смещения строки.
Распаковываем, устанавливаем позицию в файле file.txt, соответсвующую определенному
смещению и получаем из него нашу искомую строку. Все вроде бы работает, но до определенного номера строки.
Я использовал файлы с разным количеством строк: 365 и 400. Содержание строк (их длина) были разными.
Во втором файле я использовал строки с числительными (для удобства) "один", "два" и т. д.
до "четырехсот". В первом случае сбой начинался на 110 строке, во второй на 168, когда программа выдавала
значение неопределенной переменной или содержание не соответсвовало номеру строки. Разбираясь я выяснил, что,
по видимому, причина в искаженных данных, доставаемых при распаковке из index.idx. Действительно ли это
так, и что делать, как сохранить информацию, если файлы должны быть длинными? 
Код

our($line_number,$filename);
$line_number=<STDIN>;chomp $line_number;
open(INFORM, ">file.txt")||die "ОШИБКА ОТКРЫТИЯ ФАЙЛА! $!\n";
open(INDEX, "+>file.idx")||die "ОШИБКА ОТКРЫТИЯ ФАЙЛА! $!\n";

sub DAT{
my $data =shift;
my $index=shift;
my $offs=0;
while(<$data>){
print $index pack("N", $offs); #Упаковываем и записывем в индекс
$offs= tell($data); #Разбиваем на байты (побайтовое смещение строк)
              }
       };
sub IND{
my $data=shift;
my $index=shift;
my $line_numbe=shift;
my $size;
my $i_offset;
my $entry;
my $d_offset;
$size= length( pack("N",0));
$i_offset=$size*($line_number-1);
seek($index,$i_offset,0) or return;
read($index,$entry,$size); #Считываем в $entry значение смещения c позиции $i_offset
$d_offset= unpack("N",$entry);#Распаковываем индексное содержимое
seek($data,$d_offset,0);#Устанавливаем позицию в file.txt соответсвующую смещению в индексе
return scalar (<$data>); #Извлекаем нужную нам строку
       };

DAT(*INFORM,*INDEX);
$line=IND(*INFORM,*INDEX,$line_number);
print "Строка: $line\n";


PM MAIL   Вверх
Jimy
Дата 18.11.2010, 20:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 177
Регистрация: 4.7.2010

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



Файл с исходными строками (file.txt) выложите. 
PM   Вверх
ming
Дата 19.11.2010, 10:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Обязательно через индексирование?
Ведь есть специальная переменная в Perl - $., хранящая номер последней прочитанной из потока (в т.ч. файла) строки.
Код

sub get_line {
   my ($file, $line_num) = @_;
   open my $fh, '<', $file or die "$!";
   my $line;
   while($line = <$fh>) {
      next if $. < $line_num;
      last;
   }
   return $line;
}

PM MAIL ICQ Jabber   Вверх
Uran34
Дата 19.11.2010, 18:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 9.11.2010

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



Цитата(Jimy @  18.11.2010,  20:12 Найти цитируемый пост)
Файл с исходными строками (file.txt) выложите.


Выкладываю.


Присоединённый файл ( Кол-во скачиваний: 2 )
Присоединённый файл  file.txt 7,36 Kb
PM MAIL   Вверх
Uran34
Дата 19.11.2010, 18:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 9.11.2010

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



Цитата(ming @  19.11.2010,  10:55 Найти цитируемый пост)
Ведь есть специальная переменная в Perl - $., хранящая номер последней прочитанной из потока (в т.ч. файла) строки.

У меня была задача. В одном файле собрана определенная информация, строки я выбираю в зависимости
от определенного условия. Ну, например, если а==0, то берутся строки начиная с 10 и по 34, если b==1, то начиная,
допустим, со 123 и по 456 и т. д. Переменная $. запоминает первое условие и начинает работать только с него. Нельзя
присваивать переменной $. значение 10 или 123 попеременно (я долго бился, пытаясь заставить ее принимать
различные значения в зависимости от условия - безрезультатно). При индексировании можно перемещаться в файле по байтам.
 

Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  file.txt 7,36 Kb
PM MAIL   Вверх
Jimy
Дата 19.11.2010, 23:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 177
Регистрация: 4.7.2010

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



Цитата(Uran34 @ 19.11.2010,  18:00)
Цитата(Jimy @  18.11.2010,  20:12 Найти цитируемый пост)
Файл с исходными строками (file.txt) выложите.


Выкладываю.

ОС windows?

1. Строка №3 - видимо опечатка. Файл вроде надо открывать на чтение, а так он затирается.
2. Ответ на Ваш вопрос: в строку №5 добавить:
Код

binmode (INDEX);

PM   Вверх
Uran34
Дата 22.11.2010, 18:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 9.11.2010

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



Цитата(Jimy @  19.11.2010,  23:56 Найти цитируемый пост)
ОС windows?


Да

Цитата(Jimy @  19.11.2010,  23:56 Найти цитируемый пост)
1. Строка №3 - видимо опечатка. Файл вроде надо открывать на чтение, а так он затирается.


Да, конечно это опечатка.

Цитата(Jimy @  19.11.2010,  23:56 Найти цитируемый пост)
2. Ответ на Ваш вопрос: в строку №5 добавить:


ОК. Все заработало. Спасибо!

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


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

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


 




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


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

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