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

Форум PHP

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

 

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

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

тема: Постраничная навигация. Текст из файла
 
 автор: Лена   (14.12.2008 в 22:40)   письмо автору
 
 


<?php
include("configs/dbopen.php");
$number = 2000;
$offset = isset($_GET['offset']) ? (int) $_GET['offset'] : 0;
if( 
$offset < 0 ) $offset = 0;

//$id = $_GET['id'] ? intval($_GET['id']) : false;
$id = 12;
if(
$id){
$sql = "SELECT * FROM `texts` WHERE `id_mod` = 11 AND id = $id";
$result = mysql_query($sql, $link);
    while (
$row = mysql_fetch_assoc($result)){
    
$page_id = $row['page_id'];
    
$name = $row['main_text'];
    
$filename = "content/advices/" . $name . ".txt";
        
//открываем файл с текстом
        
$fp = fopen($filename, "r") or die('Could not open file');
        
flock($fp, LOCK_EX);
            
fseek($fp, $offset);
            
$pos = ftell($fp);
            
//if($pos != " ") 
            
$text = htmlspecialchars(fread($fp, $number)) . '<br />';
            
//отделяем заголовок от текста
            
if($offset == 0){
            
$head = strtok($text, "\n");
            
$head = "<div class = \"hptitle\"><h4>" . $head . "</h4></div>";
            
$text = substr($text, strpos($text, ".")+1);
            
$text = nl2br($text);
            print 
$head;
            }
            print 
$text;
            
            if(
$offset)
            
$pervpage = "<a href='?page_id=" . $page_id . "id=" . $id . "&offset=" . ($offset - $number) . "'> Назад | </a>";
            if(
$offset!=0)
            
$one = "<a href='?page_id=" . $page_id . "id=" . $id . "'> В начало | </a>";    
            if(!
feof($fp))
            
$nextpage = "<a href='?page_id=" . $page_id . "id=" . $id . "&offset=" . ($offset + $number) . "'> Вперёд | </a>";
            if(!
feof($fp))
            
$end = "<a href='?page_id=" . $page_id . "id=" . $id . "&offset=" "'> В конец | </a>";    
            
            print 
$end . $pervpage . $nextpage . $one;
        
        
flock($fp, LOCK_UN);
        
fclose($fp);
    }
}
?>


1. Если смещение приходится на середину слова(начало слова на одной странице, конец - на второй), как сделать, чтобы текст резался по пробелу? У меня это if($pos != " ") (закомментировано)
Как передвинуть смещение или влево или вправо, чтобы обрезалось по пробелу? Пробовала с помощью strpos() делать, что-то не получается.
2. Как в ссылке "В конец" - $end = "<a href='?page_id=" . $page_id . "id=" . $id . "&offset=" . $offset . "'> В конец | </a>"; найти значение offset? Как найти последнее смещение?

  Ответить  
 
 автор: Trianon   (14.12.2008 в 23:47)   письмо автору
 
   для: Лена   (14.12.2008 в 22:40)
 

Если по уму делать, то текст(ы) стоит проиндексировать, и все эти offset(s) брать из таблицы. Или из файла. Уже посчитаные.

  Ответить  
 
 автор: Лена   (15.12.2008 в 12:20)   письмо автору
 
   для: Trianon   (14.12.2008 в 23:47)
 

Переделаю, как вы сказали, потому что по-другому не получается. Пробовала еще поделить текст на слова с помощью регулярных выражений /([^\s]+\s+){$number}/, где $number - количество слов на странице, но кажется мне, что это не лучшее решение.
Смотрите, в базе есть название моего текста. Делаю еще дополнительное поле offset, записываю в нем через запятую смещения по тексту: 500, 497,499 - так, чтобы обрезалось по пробелу. Затем вытягиваю эти значения и считываю файл, учитывая смещение
или
можно разбить текстовый файл на столько файлов, сколько он займет страниц, потом в базе сделать id_child, куда занести нумерацию текстов, родителем будет id всего текста
или
внутри текста поставить какой-нибудь ограничитель и делить текст в массив по этому ограничителю, и потом выводить в цикле.
Как лучше и как быстрее работать будет?

  Ответить  
 
 автор: Trianon   (15.12.2008 в 12:41)   письмо автору
 
   для: Лена   (15.12.2008 в 12:20)
 

>Переделаю, как вы сказали, потому что по-другому не получается. Пробовала еще поделить текст на слова с помощью регулярных выражений /([^\s]+\s+){$number}/, где $number - количество слов на странице, но кажется мне, что это не лучшее решение.

Это решение можно применить именно для того, чтобы рассчитать смещения в процессе разметки.

>Смотрите, в базе есть название моего текста. Делаю еще дополнительное поле offset, записываю в нем через запятую смещения по тексту: 500, 497,499 - так, чтобы обрезалось по пробелу.
На этапе разметки - да.

>Затем вытягиваю эти значения и считываю файл, учитывая смещение
точнее - учитывая нужное смещение и разность от соседнего (это даст длину считываемого участка)

>или можно разбить текстовый файл на столько файлов, сколько он займет страниц, потом в базе сделать id_child, куда занести нумерацию текстов, родителем будет id всего текста

так тоже можно, но выдавать при необходимости документ целиком станет сильно сложнее.
я б не стал.

>или внутри текста поставить какой-нибудь ограничитель и делить текст в массив по этому ограничителю, и потом выводить в цикле.

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

  Ответить  
 
 автор: Лена   (17.12.2008 в 00:51)   письмо автору
 
   для: Trianon   (15.12.2008 в 12:41)
 


<?php
$fp 
= fopen("text.txt", "r") or die('Could not open file');
flock($fp, LOCK_EX);
$text = fread($fp, filesize("text.txt")) . "<br>";
//число слов во всем тексте
$size = str_word_count($text);
//число слов на одной странице
$number = 100; 
//число смещений
$count_off = ceil($size/$number);
//смещения в файле
$all_lenth= array();
if(
$size > $number){
    for(
$i=1;$i<$count_off+1;$i++){
    
$str = "/([^\s]+\s+){" . $number*$i . "}/";
    
preg_match($str, $text, $out); 
        
//фиксируем длину первого участка
        
if($i==1) $first_lenth = strlen($out[0][$i]);
        
//длины остальных участков(разница между соседними)
        
$lenth . "_" . $i = strlen($out[0][$i+1])-strlen($out[0][$i]);
            
//смещение, что пишется в базу
            
$offset = $lenth . "_" . $i + 1;
            
//все смещения в файле
            
$all_lenth[0] = $first_lenth;
            
$all_lenth[] = $offset;
            
//объединяем все элементы
            
$all_offset = implode(",", $all_lenth);
        
//помещаем значение $offset в базу
    
}
}
flock($fp, LOCK_UN);
fclose($fp);
?>


Не получается. Пишет Fatal error: Maximum execution time of 30 seconds exceeded in Z:\home\avart.ua\www\of.php on line 19
Причина в цикле for. Я получается сначала читаю 100 слов, потом с начала файла - 200 слов, потом опять с начала - 300 слов. Как мне сделать, чтобы каждый раз в начало не возвращаться?

  Ответить  
 
 автор: Лена   (17.12.2008 в 12:08)   письмо автору
 
   для: Лена   (17.12.2008 в 00:51)
 

Получилось.

<?php
$fp 
= fopen("a.txt", "r") or die('Could not open file'); 
flock($fp, LOCK_EX); 
$text = fread($fp, filesize("a.txt")) . "<br>"; 
$size = str_word_count($text); //число слов во всем тексте 
$number = 100;  //число слов на одной странице 
$all_lenth= array(); //смещения в файле 
if($size > $number){ 
   
$str = "/([^\s]+\s+){" . $number . "}/"; 
    
preg_match_all ($str, $text, $out); 
    for(
$i = 0;$i<count($out[0]);$i++){
    
$len = strlen($out[0][$i]);
    
$all_lenth[] = $len+1;
    }
} 
//объединяем все элементы 
$all_offset = implode(",", $all_lenth); 
//помещаем значение $offset в базу 
flock($fp, LOCK_UN); 
fclose($fp); 
?>


В базу в поле offset пишется строка типа 611,712,655,623
А дальше - выводить, как в моем первом посте, только offset берем из базы

  Ответить  
 
 автор: Trianon   (17.12.2008 в 14:19)   письмо автору
 
   для: Лена   (17.12.2008 в 12:08)
 

>В базу в поле offset пишется строка типа 611,712,655,623
Странно как-то получилось.
список смещений по идее должен быть монотонно возрастающим.
Так чтобы разность предыдущего и последующего смещений представляла собой байтовую длину текстового фрагмента...

  Ответить  
 
 автор: Лена   (17.12.2008 в 22:23)   письмо автору
 
   для: Trianon   (17.12.2008 в 14:19)
 

>список смещений по идее должен быть монотонно возрастающим.
После вашего замечания немного исправила. Спасибо. Теперь получается такая строка: 248,590,898,1252,1566,1818,2183,2493,2826,3161,3385


<?php
$fp 
= fopen("anons.txt", "r") or die('Could not open file');
flock($fp, LOCK_EX);
$text = fread($fp, filesize("anons.txt")) . "<br>";
$size = str_word_count($text); //число слов во всем тексте
$number = 30; //число слов на одной странице
$all_lenth= array(); //смещения в файле
$len_offs = ""; //разность смещений
if($size > $number){
   
$str = "/([^\s]+\s+){" . $number . "}/";
    
preg_match_all ($str, $text, $out);
        for(
$i = 0;$i<count($out[0]);$i++){
        
$len = strlen($out[0][$i]);
        
$len_offs += $len;
        
$all_lenth[] = $len_offs;
        }
}
//объединяем все элементы
$all_offset = implode(",", $all_lenth);
//print $all_offset;
//помещаем значение $offset в базу
flock($fp, LOCK_UN);
fclose($fp);
?>

  Ответить  
Rambler's Top100
вверх

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