|
|
|
| Как читать файл в обратном направлении построчно?
Конечно не загружая в массив список... | |
|
|
|
|
|
|
|
для: ValeraC
(02.05.2010 в 07:25)
| | С помощью fseek(). Отступать от конца на некоторый размер и смотреть сколько строк до конца файла. | |
|
|
|
|
|
|
|
для: Тень*
(02.05.2010 в 12:32)
| | дайте код | |
|
|
|
|
|
|
|
для: Valick
(02.05.2010 в 12:39)
| | Как читать файл в обратном направлении построчно? | |
|
|
|
|
|
|
|
для: 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) === 0 ) {
return false;
}
if( $size < 2 ) {
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($fp, min($cp, $size));
fseek($fp, -min($cp, $size), SEEK_CUR);
if( strlen($t) == 1 ) {
$buff = $t . $buff;
rewind($fp);
break;
} elseif( ($p = strrpos($t, "\n", -2)) !== false ) {
$buff = substr($t, $p + 1) . $buff;
fseek($fp, $p + 1, SEEK_CUR);
break;
} else {
$buff = $t . $buff;
}
} while( $cp > $size );
return $buff;
}
$fp = fopen(__FILE__, 'rb');
fseek($fp, 0, SEEK_END);
while( ($s = getLine($fp, 256)) !== false ) {
var_dump($s);
}
fclose($fp);
|
[поправлено модератором] | |
|
|
|
|
|
|
|
для: Тень*
(02.05.2010 в 16:38)
| | Идеально, мне понравилось, спасибо.
Ясно всем, что лучше и не придумаешь. ОК. | |
|
|
|
|
|
|
|
для: ValeraC
(02.05.2010 в 17:40)
| | 1) нет блокировки.
2) при интенсивном чтении в прямом и обратном порядке (и относительно редкой записи), лично я бы держал две копии файла соответственно прямой и обратный. | |
|
|
|
|
|
|
|
для: Valick
(02.05.2010 в 19:00)
| | > 2) при интенсивном чтении в прямом и обратном порядке (и относительно редкой записи), лично я бы держал две копии файла соответственно прямой и обратный.
Зачем?
Что вообще ужасного в чтении файла с конца?
Лучше покажите скрипт для записи в обратом порядке. Эксчендж такой. | |
|
|
|
|
|
|
|
для: Тень*
(02.05.2010 в 19:16)
| | >Лучше покажите скрипт для записи в обратом порядке. Эксчендж такой.
Разумное дополнение | |
|
|
|
|
|
|
|
для: ValeraC
(02.05.2010 в 20:10)
| | что-то и правда пока не получается нормально | |
|
|
|
|
|
|
|
для: Valick
(03.05.2010 в 14:47)
| | вот так я хотел
<?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);
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 с этим символом (квадратиком)... | |
|
|
|
|
|
|
|
для: Valick
(03.05.2010 в 18:26)
| | В каком из трёх файлов по задумке я должен получать результат в обратом порядке? Т.е. при добавлении новой строки, получать её в самом верху. | |
|
|
|
|
|
|
|
для: Тень*
(03.05.2010 в 18:32)
| | согласен держать две копии файла было бредовой идеей и не из за квадратика, а потому что при удачном стечении обстоятельств в один файл запись может иместь место, а в другой фигушки и если заморачиваться ещё и с проверкой, то вообще темный лес будет
обратный порядок в textd, файл textb используется в качестве буфера и естественно перед каждым использованием должен очищаться | |
|
|
|
|
|
|
|
для: Valick
(03.05.2010 в 18:44)
| | Почему файлы залочили, а fclose() не поставили? fgetc() зачем применять? Код тестировали?
UPD. Сейчас потестировал:
Файл atest.txt
Просто новая строка
Просто новая строка
Просто новая строка!!!!
|
Файл btest.txt
Просто новая строка
Просто новая строка
Просто новая строка
Просто новая строка!!!!
Просто новая строка
Просто новая строка
Просто новая строка
|
Файл dtest.txt
Просто новая строка
Просто новая строка
Просто новая строка
Просто новая строка!!!!
Просто новая строка
Просто новая строка
Просто новая строка
|
Причём прогнал код после изменения $string один раз.
P.S. А ведь это вполне реально написать. С использованием всего одного файла. | |
|
|
|
|
|
|
|
для: Тень*
(03.05.2010 в 18:47)
| | :) ftruncate($f,0); я убрал когда боролся с "квадратиком"
все там работает (только вот понять этот квадратик не могу... живет своей определенной жизнью)
лочить файлы нужно всегда, разлочаться сами по окончании скрипта не в этом суть... поставить недолго | |
|
|
|
|
|
|
|
для: Valick
(03.05.2010 в 18:51)
| | Итак, напишите нормальный вариант. Поставьте, где нужно, ftruncate(). Жду. | |
|
|
|
|
|
|
|
для: Тень*
(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));
?> | |
|
|
|
|
|
|
|
для: Valick
(03.05.2010 в 18:54)
| | Можно, пожалуйста, файлы именовать не $filename . "a", а "a" . $filename, т.к. вы расширение перетираете. | |
|
|
|
|
|
|
|
для: Тень*
(03.05.2010 в 18:55)
| | в смысле перетираю? его там нет совсем
на счет решения "проблемы" с одним файлом опишите в двух словах | |
|
|
|
|
|
|
|
для: 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", кстати, не делай никогда) и сместить текущее содержимое на длину вставляемой строки. | |
|
|
|
|
|
|
|
для: Тень*
(03.05.2010 в 18:59)
| |
<?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($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));
?>
|
| |
|
|
|
|
|
|
|
для: Valick
(03.05.2010 в 19:05)
| | Молодец. Видишь, можешь же, когда я заставлю захочешь. | |
|
|
|
|
|
|
|
для: Тень*
(03.05.2010 в 18:59)
| | Открывать как "rb+" ("t", кстати, не делай никогда) и сместить текущее содержимое на длину вставляемой строки.
однозначно интересно, где можно прочесть? | |
|
|
|
|
|
|
|
для: Valick
(03.05.2010 в 19:07)
| | Что именно прочесть? Я описал теорию на основании своих знаний по работе с файлами (точнее, с функциями по работе с ними). Эти функции описаны в мануале. | |
|
|
|
|
|
|
|
для: Тень*
(03.05.2010 в 19:12)
| | я всегда думал, что писать в файл можно только в конец, в смысле дописать, а не перезатереть написаное
____
Вы имееете ввиду взять 20 последних символов, сместить их на 20 символов вперёд, затем вернуться на 40 символов и так далее до самого начала? | |
|
|
|
|
|
|
|
для: Valick
(03.05.2010 в 19:16)
| | Да | |
|
|
|
|
|
|
|
для: Тень*
(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 $s) put_up("temp.txt", (++$n).". ".$s."\r\n");
?><pre><?php
readfile($name);
?>
|
PS. Втянули меня в блудняк... | |
|
|
|
|
|
|
|
для: Trianon
(03.05.2010 в 20:20)
| | Чо, выглядит нормаль. Только че-то смущает (надо же к чему-то придраться)... | |
|
|
|
|
|
|
|
для: Тень*
(03.05.2010 в 21:07)
| | Не ну просто мысль читать блоки файла от хвоста к голове - ну кощунство же это.
Опережающая буферизация на всех уровнях (от php до контроллера диска) прахом пойдет.
Как кошку против шерсти чесать... | |
|
|
|
|
|
|
|
для: Trianon
(03.05.2010 в 21:10)
| | Так лучше, да :) | |
|
|
|
|
|
|
|
для: Тень*
(03.05.2010 в 21:21)
| | Вы можете улучшить :)
я даже подскажу где.
процесс записи тоже можно сделать выровненным. | |
|
|
|
|
|
|
|
для: Trianon
(03.05.2010 в 21:56)
| | Зачем вообще нужно это:
> $blklen = ($maxlen + $blocksize-1) & ~ $blocksize;
?
И почему название такое -- $blocksize? Размер каких блоков? Не понимаю. | |
|
|
|
|
|
|
|
для: Тень*
(03.05.2010 в 22:30)
| | Ну поперед Трианона никада не успеешь.
Я еще не до конца разобрался в коде, но как я думал большой файл лучше сдвинуть блоками, а в самом конце сместить остаток | |
|
|
|
|
|
|
|
для: Valick
(03.05.2010 в 22:59)
| | Ну знаете ... я сутки терпел - с (02.05.2010 в 20:10) до восьми вечера сегодня.
Только после этого принялся что-то сочинять. | |
|
|
|
|
|
|
|
для: Trianon
(03.05.2010 в 23:58)
| | Позавчера немцы выбили партизан из леса.
Вчера партизаны выбили из леса немцев.
Сегодня пришёл лесник и разогнал партизан и немцев нахрен.
:) | |
|
|
|
|
|
|
|
для: Valick
(04.05.2010 в 00:12)
| | Не из леса.
Из избушки.
Потом пришел лесник и послал всех на... | |
|
|
|
|
|
|
|
для: Valick
(03.05.2010 в 22:59)
| | Насколько я знаю, существуют файловые системы, позволяющие управлять распределением виртуального кластерного пространства в файле не только в хвосте, но и в начале/середине.
Но соответствующие инструменты редко выводятся на уровень хотя бы минимальной портабельности.
Мне, во всяком случае, в свое время - не попадались. | |
|
|
|
|
|
|
|
для: Тень*
(03.05.2010 в 22:30)
| | Это размер единицы физической адресации данных на внешнем носителе (размер адресуемого сектора винчестера).
Привычка называть секторы блоками еще со времен pdp/11 осталась :)
А что эта строка делает - разбирайтесь. :)) | |
|
|
|