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

Форум PHP

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

 

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

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

тема: Как читать файл в обратном направлении построчно?
 
 автор: ValeraC   (02.05.2010 в 07:25)   письмо автору
 
 

Как читать файл в обратном направлении построчно?
Конечно не загружая в массив список...

  Ответить  
 
 автор: Тень*   (02.05.2010 в 12:32)   письмо автору
 
   для: ValeraC   (02.05.2010 в 07:25)
 

С помощью fseek(). Отступать от конца на некоторый размер и смотреть сколько строк до конца файла.

  Ответить  
 
 автор: Valick   (02.05.2010 в 12:39)   письмо автору
 
   для: Тень*   (02.05.2010 в 12:32)
 

дайте код

  Ответить  
 
 автор: ValeraC   (02.05.2010 в 13:07)   письмо автору
 
   для: Valick   (02.05.2010 в 12:39)
 

Как читать файл в обратном направлении построчно?

  Ответить  
 
 автор: Тень*   (02.05.2010 в 16:38)   письмо автору
 
   для: Valick   (02.05.2010 в 12:39)
 

> дайте код
<?php

error_reporting
(E_ALL E_STRICT);

set_time_limit(1);

header('Content-type: text/plain; charset=utf-8');

function 
getLine($fp$size)
{
    if( 
ftell($fp) === ) {
        return 
false;
    }

    if( 
$size ) {
        
trigger_error('WTF? Size parameter must be greater than 1'E_USER_WARNING);
        return 
false;
    }

    
$buff '';

    do {
        
$cp ftell($fp);
        
fseek($fp, -min($cp$size), SEEK_CUR);
        
$t fread($fpmin($cp$size));
        
fseek($fp, -min($cp$size), SEEK_CUR);

        if( 
strlen($t) == ) {
            
$buff $t $buff;
            
rewind($fp);
            break;           
        } elseif( (
$p strrpos($t"\n", -2)) !== false ) {
            
$buff substr($t$p 1) . $buff;
            
fseek($fp$p 1SEEK_CUR);
            break;
        } else {
            
$buff $t $buff;
        }
    } while( 
$cp $size );

    return 
$buff;
}

$fp fopen(__FILE__'rb');

fseek($fp0SEEK_END);

while( (
$s getLine($fp256)) !== false ) {
    
var_dump($s);
}

fclose($fp);

[поправлено модератором]

  Ответить  
 
 автор: ValeraC   (02.05.2010 в 17:40)   письмо автору
 
   для: Тень*   (02.05.2010 в 16:38)
 

Идеально, мне понравилось, спасибо.
Ясно всем, что лучше и не придумаешь. ОК.

  Ответить  
 
 автор: Valick   (02.05.2010 в 19:00)   письмо автору
 
   для: ValeraC   (02.05.2010 в 17:40)
 

1) нет блокировки.
2) при интенсивном чтении в прямом и обратном порядке (и относительно редкой записи), лично я бы держал две копии файла соответственно прямой и обратный.

  Ответить  
 
 автор: Тень*   (02.05.2010 в 19:16)   письмо автору
 
   для: Valick   (02.05.2010 в 19:00)
 

> 2) при интенсивном чтении в прямом и обратном порядке (и относительно редкой записи), лично я бы держал две копии файла соответственно прямой и обратный.

Зачем?
Что вообще ужасного в чтении файла с конца?

Лучше покажите скрипт для записи в обратом порядке. Эксчендж такой.

  Ответить  
 
 автор: ValeraC   (02.05.2010 в 20:10)   письмо автору
 
   для: Тень*   (02.05.2010 в 19:16)
 

>Лучше покажите скрипт для записи в обратом порядке. Эксчендж такой.
Разумное дополнение

  Ответить  
 
 автор: Valick   (03.05.2010 в 14:47)   письмо автору
 
   для: ValeraC   (02.05.2010 в 20:10)
 

что-то и правда пока не получается нормально

  Ответить  
 
 автор: Valick   (03.05.2010 в 18:26)   письмо автору
 
   для: Valick   (03.05.2010 в 14:47)
 

вот так я хотел

<?php
$string 
"Просто новая строка\n";
$filename "text";
$fa=fopen($filename."a""r+t") or die("Невозможно открыть файл");
    while(!
flock($faLOCK_EX+LOCK_NB)) sleep(1);
    
$fd=fopen($filename."d""r+t") or die("Невозможно открыть файл");
        while(!
flock($fdLOCK_EX+LOCK_NB)) sleep(1);
    
fseek($fa,0,SEEK_END);
    
fwrite($fa,$string);

    
$fb=fopen($filename."b""r+t") or die("Невозможно открыть файл");
          while(!
flock($fbLOCK_EX+LOCK_NB)) sleep(1);

    
fseek($fb,0,SEEK_END);
    
fwrite($fb,$string);

    
fseek($fd,0,SEEK_SET);
    
$size=filesize($filename."d");
    if(
$size>0) while(!feof($fd)) fputs($fb,fgetc($fd));
    
fseek($fb,0,SEEK_SET);
    
fseek($fd,0,SEEK_SET);
    while(!
feof($fb)) fputs($fd,fgetc($fb));
?>


но хоть тресни не пойму почему в texta создается запись без управляющего символа после перевода строки, а в файле textb с этим символом (квадратиком)...

  Ответить  
 
 автор: Тень*   (03.05.2010 в 18:32)   письмо автору
 
   для: Valick   (03.05.2010 в 18:26)
 

В каком из трёх файлов по задумке я должен получать результат в обратом порядке? Т.е. при добавлении новой строки, получать её в самом верху.

  Ответить  
 
 автор: Valick   (03.05.2010 в 18:44)   письмо автору
 
   для: Тень*   (03.05.2010 в 18:32)
 

согласен держать две копии файла было бредовой идеей и не из за квадратика, а потому что при удачном стечении обстоятельств в один файл запись может иместь место, а в другой фигушки и если заморачиваться ещё и с проверкой, то вообще темный лес будет

обратный порядок в textd, файл textb используется в качестве буфера и естественно перед каждым использованием должен очищаться

  Ответить  
 
 автор: Тень*   (03.05.2010 в 18:47)   письмо автору
 
   для: Valick   (03.05.2010 в 18:44)
 

Почему файлы залочили, а fclose() не поставили? fgetc() зачем применять? Код тестировали?

UPD. Сейчас потестировал:

Файл atest.txt
Просто новая строка
Просто новая строка
Просто новая строка!!!!


Файл btest.txt
Просто новая строка
Просто новая строка
Просто новая строка
Просто новая строка!!!!
Просто новая строка
Просто новая строка
Просто новая строка


Файл dtest.txt
Просто новая строка
Просто новая строка
Просто новая строка
Просто новая строка!!!!
Просто новая строка
Просто новая строка
Просто новая строка


Причём прогнал код после изменения $string один раз.

P.S. А ведь это вполне реально написать. С использованием всего одного файла.

  Ответить  
 
 автор: Valick   (03.05.2010 в 18:51)   письмо автору
 
   для: Тень*   (03.05.2010 в 18:47)
 

:) ftruncate($f,0); я убрал когда боролся с "квадратиком"

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

  Ответить  
 
 автор: Тень*   (03.05.2010 в 18:53)   письмо автору
 
   для: Valick   (03.05.2010 в 18:51)
 

Итак, напишите нормальный вариант. Поставьте, где нужно, ftruncate(). Жду.

  Ответить  
 
 автор: Valick   (03.05.2010 в 18:54)   письмо автору
 
   для: Тень*   (03.05.2010 в 18:53)
 

<?php
$string = "Просто новая строка\n";
$filename = "text";
$fa=fopen($filename."a", "r+t") or die("Невозможно открыть файл");
while(!flock($fa, LOCK_EX+LOCK_NB)) sleep(1);
$fd=fopen($filename."d", "r+t") or die("Невозможно открыть файл");
while(!flock($fd, LOCK_EX+LOCK_NB)) sleep(1);
fseek($fa,0,SEEK_END);
fwrite($fa,$string);

$fb=fopen($filename."b", "r+t") or die("Невозможно открыть файл");
while(!flock($fb, LOCK_EX+LOCK_NB)) sleep(1);
ftruncate($f,0);
fseek($fb,0,SEEK_END);
fwrite($fb,$string);

fseek($fd,0,SEEK_SET);
$size=filesize($filename."d");
if($size>0) while(!feof($fd)) fputs($fb,fgetc($fd));
fseek($fb,0,SEEK_SET);
fseek($fd,0,SEEK_SET);
while(!feof($fb)) fputs($fd,fgetc($fb));
?>

  Ответить  
 
 автор: Тень*   (03.05.2010 в 18:55)   письмо автору
 
   для: Valick   (03.05.2010 в 18:54)
 

Можно, пожалуйста, файлы именовать не $filename . "a", а "a" . $filename, т.к. вы расширение перетираете.

  Ответить  
 
 автор: Valick   (03.05.2010 в 18:57)   письмо автору
 
   для: Тень*   (03.05.2010 в 18:55)
 

в смысле перетираю? его там нет совсем
на счет решения "проблемы" с одним файлом опишите в двух словах

  Ответить  
 
 автор: Тень*   (03.05.2010 в 18:59)   письмо автору
 
   для: Valick   (03.05.2010 в 18:57)
 

В том-то и дело, что для теста для задаю имя файла с расширением. Мне кажется, так удобнее.

Ваш скрипт выдает:

Notice: Undefined variable: f in ... on line 16

Warning: ftruncate() expects parameter 1 to be resource, null given in ... on line 16


Не торопитесь. Сделайте отладку, а только потом показывайте.

> на счет решения "проблемы" с одним файлом опишите в двух словах
Открывать как "rb+" ("t", кстати, не делай никогда) и сместить текущее содержимое на длину вставляемой строки.

  Ответить  
 
 автор: Valick   (03.05.2010 в 19:05)   письмо автору
 
   для: Тень*   (03.05.2010 в 18:59)
 


<?php
$string 
"Просто новая строка\n";
$filename "text";
$fa=fopen($filename."a""r+t") or die("Невозможно открыть файл");
    while(!
flock($faLOCK_EX+LOCK_NB)) sleep(1);
    
$fd=fopen($filename."d""r+t") or die("Невозможно открыть файл");
        while(!
flock($fdLOCK_EX+LOCK_NB)) sleep(1);
    
fseek($fa,0,SEEK_END);
    
fwrite($fa,$string);

    
$fb=fopen($filename."b""r+t") or die("Невозможно открыть файл");
          while(!
flock($fbLOCK_EX+LOCK_NB)) sleep(1);
    
ftruncate($fb,0);
    
fseek($fb,0,SEEK_END);
    
fwrite($fb,$string);

    
fseek($fd,0,SEEK_SET);
    
$size=filesize($filename."d");
    if(
$size>0) while(!feof($fd)) fputs($fb,fgetc($fd));
    
fseek($fb,0,SEEK_SET);
    
fseek($fd,0,SEEK_SET);
    while(!
feof($fb)) fputs($fd,fgetc($fb));
?>

  Ответить  
 
 автор: Тень*   (03.05.2010 в 19:11)   письмо автору
 
   для: Valick   (03.05.2010 в 19:05)
 

Молодец. Видишь, можешь же, когда я заставлю захочешь.

  Ответить  
 
 автор: Valick   (03.05.2010 в 19:07)   письмо автору
 
   для: Тень*   (03.05.2010 в 18:59)
 

Открывать как "rb+" ("t", кстати, не делай никогда) и сместить текущее содержимое на длину вставляемой строки.
однозначно интересно, где можно прочесть?

  Ответить  
 
 автор: Тень*   (03.05.2010 в 19:12)   письмо автору
 
   для: Valick   (03.05.2010 в 19:07)
 

Что именно прочесть? Я описал теорию на основании своих знаний по работе с файлами (точнее, с функциями по работе с ними). Эти функции описаны в мануале.

  Ответить  
 
 автор: Valick   (03.05.2010 в 19:16)   письмо автору
 
   для: Тень*   (03.05.2010 в 19:12)
 

я всегда думал, что писать в файл можно только в конец, в смысле дописать, а не перезатереть написаное
____
Вы имееете ввиду взять 20 последних символов, сместить их на 20 символов вперёд, затем вернуться на 40 символов и так далее до самого начала?

  Ответить  
 
 автор: Тень*   (03.05.2010 в 19:40)   письмо автору
 
   для: Valick   (03.05.2010 в 19:16)
 

Да

  Ответить  
 
 автор: Trianon   (03.05.2010 в 20:20)   письмо автору
 
   для: Тень*   (03.05.2010 в 19:40)
 

<?php

    $name 
"temp.txt";


    function 
put_up($name$data$maxbuf 8192$blocksize 512)
    {

      
$len $datalength strlen($data);

      
$maxlen max($datalength$maxbuf);
      
$blklen = ($maxlen $blocksize-1) & ~ $blocksize;

      if(!(
$fr = @fopen($name"rb")))
      {
          
$fw fopen($name"wb");
          
fwrite($fw$data);
          
fclose($fw);
          return;
      }

      
$fw fopen($name"rb+");

      do
      {
          
$next fread($fr$blklen);
          
fwrite($fw$data);
          
$data $next$next '';
      }
      while(!
feof($fr));

      
fwrite($fw$data);
      
fclose($fr);
      
fclose($fw);
    }

    
$n 0;
    @
unlink($name);
    foreach( 
glob("*.*") as $sput_up("temp.txt", (++$n).". ".$s."\r\n");
    
?><pre><?php
    readfile
($name);
?>



PS. Втянули меня в блудняк...

  Ответить  
 
 автор: Тень*   (03.05.2010 в 21:07)   письмо автору
 
   для: Trianon   (03.05.2010 в 20:20)
 

Чо, выглядит нормаль. Только че-то смущает (надо же к чему-то придраться)...

  Ответить  
 
 автор: Trianon   (03.05.2010 в 21:10)   письмо автору
 
   для: Тень*   (03.05.2010 в 21:07)
 

Не ну просто мысль читать блоки файла от хвоста к голове - ну кощунство же это.
Опережающая буферизация на всех уровнях (от php до контроллера диска) прахом пойдет.
Как кошку против шерсти чесать...

  Ответить  
 
 автор: Тень*   (03.05.2010 в 21:21)   письмо автору
 
   для: Trianon   (03.05.2010 в 21:10)
 

Так лучше, да :)

  Ответить  
 
 автор: Trianon   (03.05.2010 в 21:56)   письмо автору
 
   для: Тень*   (03.05.2010 в 21:21)
 

Вы можете улучшить :)
я даже подскажу где.
процесс записи тоже можно сделать выровненным.

  Ответить  
 
 автор: Тень*   (03.05.2010 в 22:30)   письмо автору
 
   для: Trianon   (03.05.2010 в 21:56)
 

Зачем вообще нужно это:
> $blklen = ($maxlen + $blocksize-1) & ~ $blocksize;
?
И почему название такое -- $blocksize? Размер каких блоков? Не понимаю.

  Ответить  
 
 автор: Valick   (03.05.2010 в 22:59)   письмо автору
 
   для: Тень*   (03.05.2010 в 22:30)
 

Ну поперед Трианона никада не успеешь.
Я еще не до конца разобрался в коде, но как я думал большой файл лучше сдвинуть блоками, а в самом конце сместить остаток

  Ответить  
 
 автор: Trianon   (03.05.2010 в 23:58)   письмо автору
 
   для: Valick   (03.05.2010 в 22:59)
 

Ну знаете ... я сутки терпел - с (02.05.2010 в 20:10) до восьми вечера сегодня.
Только после этого принялся что-то сочинять.

  Ответить  
 
 автор: Valick   (04.05.2010 в 00:12)   письмо автору
 
   для: Trianon   (03.05.2010 в 23:58)
 

Позавчера немцы выбили партизан из леса.
Вчера партизаны выбили из леса немцев.
Сегодня пришёл лесник и разогнал партизан и немцев нахрен.
:)

  Ответить  
 
 автор: Trianon   (04.05.2010 в 00:28)   письмо автору
 
   для: Valick   (04.05.2010 в 00:12)
 

Не из леса.
Из избушки.
Потом пришел лесник и послал всех на...

  Ответить  
 
 автор: Trianon   (04.05.2010 в 00:01)   письмо автору
 
   для: Valick   (03.05.2010 в 22:59)
 

Насколько я знаю, существуют файловые системы, позволяющие управлять распределением виртуального кластерного пространства в файле не только в хвосте, но и в начале/середине.
Но соответствующие инструменты редко выводятся на уровень хотя бы минимальной портабельности.
Мне, во всяком случае, в свое время - не попадались.

  Ответить  
 
 автор: Trianon   (03.05.2010 в 23:53)   письмо автору
 
   для: Тень*   (03.05.2010 в 22:30)
 

Это размер единицы физической адресации данных на внешнем носителе (размер адресуемого сектора винчестера).
Привычка называть секторы блоками еще со времен pdp/11 осталась :)
А что эта строка делает - разбирайтесь. :))

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

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