A better example, to illustrate the differences in speed for large files, between fgets and stream_get_line.
This example simulates situations where you are reading potentially very long lines, of an uncertain length (but with a maximum buffer size), from an input source.
As Dade pointed out, the previous example I provided was much to easy to pick apart, and did not adequately highlight the issue I was trying to address.
Note that specifying a definitive end-character for fgets (ie: newline), generally decreases the speed difference reasonably significantly.
#!/usr/bin/php
<?php
$plaintext=file_get_contents('http://loripsum.net/api/60/verylong/plaintext'); # Should be around 90k characters
$plaintext=str_replace("\n"," ",$plaintext); # Get rid of newlines
$fp=fopen("/tmp/SourceFile.txt","w");
for($i=0;$i<100000;$i++) {
fputs($fp,substr($plaintext,0,rand(4096,65534)) . "\n");
}
fclose($fp);
$fp=fopen("/tmp/SourceFile.txt","r");
$start=microtime(true);
while($line=fgets($fp,65535)) {
1;
}
$end=microtime(true);
fclose($fp);
$delta1=($end - $start);
$fp=fopen("/tmp/SourceFile.txt","r");
$start=microtime(true);
while($line=stream_get_line($fp,65535)) {
1;
}
$end=microtime(true);
fclose($fp);
$delta2=($end - $start);
$pdiff=$delta1/$delta2;
print "stream_get_line is " . ($pdiff>1?"faster":"slower") . " than fgets - pdiff is $pdiff\n";
?>
$ ./testcase.php
stream_get_line is faster than fgets - pdiff is 1.760398041785
Note that, in a vast majority of situations in which php is employed, tiny differences in speed between system calls are of negligible importance.fgets
Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.
fgets
Референца за `function.fgets.php` со подобрена типографија и навигација.
fgets
(PHP 4, PHP 5, PHP 7, PHP 8)
fgets — Зема ред од покажувач на датотека
= NULL
Зема ред од покажувач на датотека.
Параметри
stream-
Показалецот на датотеката мора да биде валиден и мора да покажува на датотека успешно отворена од fopen() or fsockopen() ) на наведениот fclose()).
length-
Читањето завршува кога
length- 1 бајти се прочитани, или нов ред (што е вклучено во вратената вредност), или EOF (кое и да дојде прво). Ако не е специфицирана должина, ќе продолжи да чита од протокот додека не го достигне крајот на редот.
Вратени вредности
Враќа стринг до length - 1 бајти прочитани од датотеката посочена од stream. Ако нема повеќе податоци за читање во покажувачот на датотека, тогаш false се враќа.
Ако се појави грешка, false се враќа.
Примери
Пример #1 Читање датотека ред по ред
<?php
$fp = @fopen("/tmp/inputfile.txt", "r");
if ($fp) {
while (($buffer = fgets($fp, 4096)) !== false) {
echo $buffer, PHP_EOL;
}
if (!feof($fp)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($fp);
}
?>Белешки
Забелешка: Ако PHP правилно не ги препознава крајот на редовите при читање датотеки на или создадени од Macintosh компјутер, овозможувањето на auto_detect_line_endings опцијата за конфигурација во тек може да помогне да се реши проблемот.
Забелешка:
Луѓето навикнати на 'C' семантиката на fgets() треба да ја забележат разликата во тоа како
EOFсе враќа.
Види Исто така
- fgetss() - Поставете блокирачки/неблокирачки режим на стрим
- fread() - Зема ред од датотека
- fgetc() - Земи карактер од покажувач на датотека
- stream_get_line() - Земи ред од ресурс на протокот до даден разделувач
- fopen() - Отвора датотека или URL
- popen() - Поставува период на чекање на поток
- fsockopen() - Бинарно запишување во датотека
- stream_set_timeout() - Проверува дали датотеката постои и може да се чита
Белешки од корисници 5 белешки
if you for some reason need to get lines from a string instead of a file pointer, try
<?php
function string_gets(string $source, int $offset = 0, string $delimiter = "\n"): ?string
{
$len = strlen($source);
if ($len < $offset) {
// out of bounds.. maybe i should throw an exception
return null;
}
if ($len === $offset) {
// end of string..
return null;
}
$delimiter_pos = strpos($source, $delimiter, $offset);
if ($delimiter_pos === false) {
// last line.
return substr($source, $offset);
}
return substr($source, $offset, ($delimiter_pos - $offset) + strlen($delimiter));
}
?>
(i had a ~16GB string in-memory i needed to process line-by-line, but i would get memory-allocation-crash (on a 32GB ram system) if i tried explode("\n",$str); , so came up with this.. interestingly, fgets() seems to be faster than doing it in-ram-in-php, though. php 7.3.7)There's an error in the documentation:
The file pointer must be valid, and must point to a file successfully opened by fopen() or fsockopen() (and not yet closed by fclose()).
You should also add "popen" and "pclose" to the documentation. I'm a new PHP developer and went to verify that I could use "fgets" on commands that I used with "popen".fscanf($file, "%s\n") isn't really a good substitution for fgets(), since it will stop parsing at the first whitespace and not at the end of line!
(See the fscanf page for details on this)I think that the quickest way of read a (long) file with the rows in reverse order is
<?php
$myfile = 'myfile.txt';
$command = "tac $myfile > /tmp/myfilereversed.txt";
passthru($command);
$ic = 0;
$ic_max = 100; // stops after this number of rows
$handle = fopen("/tmp/myfilereversed.txt", "r");
while (!feof($handle) && ++$ic<=$ic_max) {
$buffer = fgets($handle, 4096);
echo $buffer."<br>";
}
fclose($handle);
?>
It echos the rows while it is reading the file so it is good for long files like logs.
Borgonovo