Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Ответ 002 на задачу N 12
 
 автор: SoftTime   (17.03.2006 в 23:11)   письмо автору
 
 

Ответ 002 на задачу N 12.
С условиями задачи можно ознакомится по ссылке.
У меня два решения.
Одно для относительно небольших файлов (до 300 кБ)

<?php
   $def
=array('page' =>1'num' => 10'set' => 20);

   
$f fopen("data.txt"'r');
   if(isset(
$_GET['total']))
      
$total intval($_GET['total']);
   else
   {
       for(
$i 0; !feof($f); $i++) $s fgets($f);
       
rewind($f);
       
$total $i - (trim($s) == "");
   }
   foreach(
$def as $k => $v)
     $
$k = isset($_GET[$k])&& $_GET[$k] > $_GET[$k]: $v;

   
$page_i 1;
   for(
$lines 0$lines $total$page_i++)
   {
       
$lines += $num $set;
       if(
$page_i == $page)
          echo 
"$page_i\r\n";
       else
          echo 
"<a href=?total=$total&num=$num&set=$set&page=$page_i>"
               
.$page_i"</a>\r\n";
   }
   if(
$page >= $page_i)
         
$page $page_i-1;
   
$lines_start = ($page-1) * $num $set;

   for(
$i 0; !feof($f) && $i $lines_start$i++) fgets($f);

   for(
$j ; !feof($f) && $j $num$j++)
   {
       echo 
'<hr>';
       for(
$i ; !feof($f) && $i $set$i++)
           echo 
fgets($f)."<br>\r\n";
   }
?>


Другое решение - для очень больших файлов. Более 1Мб.

<?php
   $def
=array('page' =>1'num' => 10'set' => 20);
   
$txtname = isset($_GET['file']) ? $_GET['file'] : "data.txt";
   
$tfd fopen($txtname'r') or die("cannot open $file");
   
$tsize filesize($txtname);
   
$ttime filemtime($txtname);
   
$idxname $txtname .".idx";
   for(
$try=0$try &&     // Попытаемся 1 раз перестроить индекс, если
        
(  ($ifd= @fopen($idxname"r"))==0   // нет индекса
       
|| ($isize = @fgets($ifd)) != $tsize  // файл дописали
       
|| ($mult =  @ftell($ifd)) <= 3         // мал размер элемента индекса
       
|| ($itime = @fgets($ifd)) != $ttime  // файл изменили
       
|| ($ibase = @fgets($ifd)) == 0       // база индекса не определена
       
||  $ibase != @ftell($ifd)              // база индекса не достигнута
        
); $try++ )                          //
   
{                                        //строим нафиг свежий индекс
      
if($ifdfclose($ifd);
      
$ifd fopen($idxname"w") or die("cannot create index $idxname");
      
$sizewidth strlen("$tsize");
      if(
$sizewidth 2$sizewidth 2;
      
fprintf($ifd"%${sizewidth}d\n"$tsize);
      
$mult ftell($ifd);

      
$timewidth strlen("$ttime");
      while(
$timewidth $sizewidth || ($timewidth-$sizewidth)%$mult) ++ $timewidth;
      
fprintf($ifd"%${timewidth}d\n"$ttime);
      
$ibase ftell($ifd)+ $mult;
      
fprintf($ifd"%${sizewidth}d\n",  $ibase);
      if(
ftell($ifd) != $ibase)
          
$try 2;

      for(;!
feof($tfd); fgets($tfd))
         if((
$pos ftell($tfd)) < $tsize)
             
fprintf($ifd"%${sizewidth}d\n"$pos);
      
fclose($ifd);
   }
   if(
$try <= 1)
   {
       
fseek($ifd0SEEK_END);
       
$iend ftell($ifd);
       
$total intval(($iend $ibase)/$mult);
   }
   if(
$try || $total $mult +$ibase != $iend)
          die (
"Ну не умею я строить индекс. И вообще я обиделась.");
   foreach(
$def as $k => $v)
     $
$k = isset($_GET[$k])&& $_GET[$k] > $_GET[$k]: $v;

   
$page_i 1;

   for(
$lines 0$lines $total$page_i++)
   {
       
$lines += $num $set;
       if(
$page_i == $page)
          echo 
"$page_i\r\n";
       else
          echo 
"<a href=?file=".urlencode($txtname)."&num=$num&set=$set&page=$page_i>"
               
.$page_i"</a>\r\n";
   }
   if(
$page >= $page_i)
         
$page $page_i-1;
   
$lines_start = ($page-1) * $num $set;

   
fseek($ifd$ibase+$mult *$lines_startSEEK_SET);
   
fseek($tfdtrim(fgets($ifd)), SEEK_SET);

   for(
$j ; !feof($tfd) && $j $num$j++)
   {
       echo 
'<hr>';
       for(
$i ; !feof($tfd) && $i $set$i++)
           echo 
fgets($tfd)."<br>\r\n";
   }

?>

Trianon

http://www.softtime.ru/info/task.php?id_article=82

   
 
 автор: cheops   (19.03.2006 в 23:36)   письмо автору
 
   для: SoftTime   (17.03.2006 в 23:11)
 

Хитро... хм... не очень понятно что скрипт делает - у меня выводится всё содержимое файла на одной странице, прчём то что должно быть отдельной странице отделяется друг от друга <hr>. При этом сама постраничная навигация не реализуется...

   
 
 автор: Trianon   (20.03.2006 в 00:30)   письмо автору
 
   для: cheops   (19.03.2006 в 23:36)
 

Страницы по условиям задачи состоят из n( у меня num=10) блоков по s (у меня set=20) строк. То есть в каждой странице 10*20 =200 строк. Умолчания можно поменять в скрипте. Или можно вручную вызвать скрипт, указав другие значения num и set: ?num=5&set=4 например. Наконец, можно погонять скрипт на немного бОльших файлах. 1000 строк например.
Или на реально БОЛЬШИХ файлах. Пару десятков миллионов строк например. А потом сравнить результат с другими решениями. Это к вопросу о реально работающих скриптах. :)

   
 
 автор: cheops   (20.03.2006 в 13:16)   письмо автору
 
   для: Trianon   (20.03.2006 в 00:30)
 

Хм... а где меню 1 2 3 4 5 6 на страницы?

   
 
 автор: Trianon   (20.03.2006 в 13:48)   письмо автору
 
   для: cheops   (20.03.2006 в 13:16)
 

Самая первая строка - это и есть меню :)
Для файла в 100 строк - а это одна станица (точнее - ровно половина страницы :)) В первой строке будет написано
1
Что, согласитесь, верно. Оглавление содержит название только одной страницы. И поскольку эта страница как раз показана, ссылкой это название не обрамлено.

Да, я был неправ, что в отосланных решениях оставил настройки умолчаний параметров на размер страницы в 200 строк (это произошло потому, что тестировался я на файле из нескольких тысяч строк). Надо было написать num => 4, set =>5, и в таком виде постить ответ.

   
 
 автор: cheops   (20.03.2006 в 13:51)   письмо автору
 
   для: Trianon   (20.03.2006 в 13:48)
 

Хм... вообще предполагалось что-то вот такое http://www.softtime.ru/forum/read.php?id_forum=7&id_theme=14744 - т.е. обычная не затейлевая постраничная навигация при выводе из файла... может конечно, задач слишком формально задана...

   
 
 автор: Trianon   (20.03.2006 в 14:15)   письмо автору
 
   для: cheops   (20.03.2006 в 13:51)
 

Могу лишь объяснить как её понял я.
То, что требуется навигация по файлу , а не по массиву объектов, было подчеркнуто даже в названии задачи. Файловая постраничная навигация. А файл спокон веку был объектом, который имеет право не помещаться в оперативную память. Тем более, когда ссылка на файловую сущность идет в постановке задачи. Раз требуется листать по страницам, значит объект запросто может оказаться большим. А скрипт не имеет права на нем тормозить, и уж всяко - ломаться.

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования