Heim  >  Artikel  >  Backend-Entwicklung  >  Beispielvergleich, wie PHP große Dateien effizient liest

Beispielvergleich, wie PHP große Dateien effizient liest

*文
*文Original
2017-12-29 18:59:442165Durchsuche

Das Lesen großer Dateien war schon immer ein Problem. Wenn wir beispielsweise PHP zum Entwickeln und Lesen kleiner Dateien verwenden, können wir dies direkt erreichen, sobald wir zu einem großen Artikel kommen Die häufig verwendeten Methoden können nicht normal verwendet werden oder dauern zu lange. Schauen wir uns die Lösung für das Problem des Lesens großer Dateien in PHP an.

In PHP ist die Verwendung einiger Funktionen wie file und file_get_contents die schnellste Möglichkeit, dies mit nur wenigen Codezeilen zu erreichen. Wenn es sich bei der zu bearbeitenden Datei jedoch um eine relativ große Datei handelt, reichen diese Funktionen möglicherweise nicht aus. Im Folgenden werden zunächst die häufig verwendeten Betriebsmethoden beim Lesen großer Dateien erläutert.

Anforderungen:
Es gibt eine 800 MB große Protokolldatei mit etwa 5 Millionen Zeilen. Verwenden Sie PHP, um den Inhalt der letzten paar Zeilen zurückzugeben.

Implementierungsmethode:

1. Verwenden Sie direkt die Dateifunktion, um zu arbeiten
Da die Dateifunktion den gesamten Inhalt auf einmal in den Speicher liest und PHP einige Fehler verhindert Wenn geschriebene Programme zu viel Speicher belegen, führt dies zu einem Absturz des Servers. Daher ist die maximale Speichernutzung durch „memory_limit = 16M“ in php.ini festgelegt -1 , die Speichernutzung ist unbegrenzt.

Das Folgende ist ein Codestück, das file verwendet, um die letzte Zeile dieser Datei zu extrahieren:

<?php
  ini_set(&#39;memory_limit&#39;, &#39;-1&#39;);
  $file = &#39;access.log&#39;;
  $data = file($file);
  $line = $data[count($data) - 1];
  echo $line;
?>

Die Ausführung des gesamten Codes dauert 116,9613 (s).
Wenn ich zum Ausführen F5 drücke, wird das System nach fast 20 Minuten sofort ausgegraut. Es ist ersichtlich, dass das direkte Einlesen einer so großen Datei schwerwiegende Folgen hat Als letzten Ausweg darf „memory_limit“ nicht zu hoch eingestellt werden, andernfalls müssen Sie den Computerraum anrufen, um die Maschine zurückzusetzen.

2. Rufen Sie direkt den Linux-Tail-Befehl auf, um die letzten paar Zeilen anzuzeigen
Unter der Linux-Befehlszeile können Sie tail -n 10 access.log direkt verwenden, um die letzten paar Zeilen des Protokolls einfach anzuzeigen Sie können PHP direkt verwenden, um den Befehl tail aufzurufen und den PHP-Code wie folgt auszuführen:

<?php
  $file = &#39;access.log&#39;;
  $file = escapeshellarg($file); // 对命令行参数进行安全转义
  $line = `tail -n 1 $file`;
  echo $line;
?>

Die gesamte Codeausführung dauert 0,0034 (s)

3 um Dateioperationen auszuführen
Diese Methode ist die gebräuchlichste Methode. Sie muss nicht den gesamten Inhalt der Datei lesen, sondern arbeitet direkt über Zeiger, sodass die Effizienz recht effizient ist. Bei der Verwendung von fseek zum Bearbeiten von Dateien gibt es viele verschiedene Methoden, und die Effizienz kann geringfügig unterschiedlich sein. Die folgenden zwei häufig verwendeten Methoden sind:

Methode 1
Suchen Sie zuerst die Datei über fseek. Das letzte EOF. Suchen Sie dann die Startposition der letzten Zeile, rufen Sie die Daten dieser Zeile ab, ermitteln Sie dann die Startposition der nächsten Zeile, übernehmen Sie dann die Position dieser Zeile und so weiter, bis die Zeile $num gefunden wird.
Der Implementierungscode lautet wie folgt

<?php
$fp = fopen($file, "r");
$line = 10;
$pos = -2;
$t = " ";
$data = "";
while ($line > 0)
{
 while ($t != "\n")
 {
 fseek($fp, $pos, SEEK_END);
 $t = fgetc($fp);
 $pos--;
 }
 $t = " ";
 $data .= fgets($fp);
 $line--;
}
fclose($fp);
echo $data
?>

Die gesamte Codeausführung dauert 0,0095 (s)

Methode 2
Ich verwende weiterhin fseek, um vom Ende der Datei an zu lesen. Diesmal wird jedoch nicht Stück für Stück, sondern Stück für Stück gelesen. Jedes Mal, wenn ein Datenelement gelesen wird, werden die gelesenen Daten in einen Puffer gestellt und dann die Anzahl der Zeilenumbruchzeichen (\n) zur Bestimmung verwendet ob es gelesen wurde. Vervollständigen Sie die letzten $num Datenzeilen.
Der Implementierungscode lautet wie folgt

<?php
$fp = fopen($file, "r");
$num = 10;
$chunk = 4096;
$fs = sprintf("%u", filesize($file));
$max = (intval($fs) == PHP_INT_MAX) ? PHP_INT_MAX : filesize($file);
for ($len = 0; $len < $max; $len += $chunk)
{
 $seekSize = ($max - $len > $chunk) ? $chunk : $max - $len;
 fseek($fp, ($len + $seekSize) * -1, SEEK_END);
 $readData = fread($fp, $seekSize) . $readData;
 if (substr_count($readData, "\n") >= $num + 1)
 {
 preg_match("!(.*?\n){" . ($num) . "}$!", $readData, $match);
 $data = $match[0];
 break;
 }
}
fclose($fp);
echo $data;
?>

Die gesamte Codeausführung dauert 0,0009(s).

Methode 3

<?php
function tail($fp, $n, $base = 5)
{
 assert($n > 0);
 $pos = $n + 1;
 $lines = array();
 while (count($lines) <= $n)
 {
 try
 {
  fseek($fp, -$pos, SEEK_END);
 }
 catch (Exception $e)
 {
  fseek(0);
  break;
 }
 $pos *= $base;
 while (!feof($fp))
 {
  array_unshift($lines, fgets($fp));
 }
 }
 return array_slice($lines, 0, $n);
}
var_dump(tail(fopen("access.log", "r+"), 10));
?>

Die gesamte Codeausführung dauert 0,0003(s)

Methode 4, PHPs stream_get_line-Funktion, schnelles Lesen, 500.000 Zeilen lesen Für große Datendateien, es kann etwa 20 Sekunden dauern! Der Beispielcode lautet wie folgt:

$fp = fopen(&#39;./iis.log&#39;, &#39;r&#39;); //文件 
while (!feof($fp)) { 
 //for($j=1;$j<=1000;$j++) {     //读取下面的1000行并存储到数组中 
 $logarray[] = stream_get_line($fp, 65535, "\n"); 
    // break;
 // } 
 
 }

Verwandte Empfehlungen:

Detaillierte Erläuterung der Methoden zum Lesen von PHP-Dateien in Serien

PHP-Datei lesen fread, fgets, fgetc, file_get_contents und Beispielcode für die Verwendung von Dateifunktionen

Eine kurze Einführung in PHP-Dateisperre und Prozesssperre

Das obige ist der detaillierte Inhalt vonBeispielvergleich, wie PHP große Dateien effizient liest. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn