Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр 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] > 0 ? $_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 = 0 ; !feof($f) && $j < $num; $j++)
   {
       echo 
'<hr>';
       for(
$i = 0 ; !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 < 2 &&     // Попытаемся 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($ifd) fclose($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($ifd, 0, SEEK_END);
       
$iend = ftell($ifd);
       
$total = intval(($iend - $ibase)/$mult);
   }
   if(
$try > 1 || $total * $mult +$ibase != $iend)
          die (
"Ну не умею я строить индекс. И вообще я обиделась.");
   foreach(
$def as $k => $v)
     $
$k = isset($_GET[$k])&& $_GET[$k] > 0 ? $_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_start, SEEK_SET);
   
fseek($tfd, trim(fgets($ifd)), SEEK_SET);

   for(
$j = 0 ; !feof($tfd) && $j < $num; $j++)
   {
       echo 
'<hr>';
       for(
$i = 0 ; !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 Яндекс.Метрика Яндекс цитирования