Maison  >  Article  >  développement back-end  >  Comparaison d'exemples montrant comment PHP peut lire efficacement des fichiers volumineux

Comparaison d'exemples montrant comment PHP peut lire efficacement des fichiers volumineux

*文
*文original
2017-12-29 18:59:442122parcourir

La lecture de gros fichiers a toujours été un casse-tête. Par exemple, si nous utilisons PHP pour développer et lire de petits fichiers, nous pouvons utiliser directement diverses fonctions pour y parvenir. Cependant, une fois que nous arriverons à un gros article, nous constaterons cela. les méthodes couramment utilisées ne peuvent pas être utilisées normalement ou prennent trop de temps. Jetons un coup d'œil à la solution au problème de lecture de gros fichiers en PHP. J'espère que cela sera utile à tout le monde.

En PHP, le moyen le plus rapide de lire des fichiers est d'utiliser certaines fonctions telles que file et file_get_contents. Cela peut être complété à merveille avec seulement quelques lignes de code. Mais lorsque le fichier exploité est un fichier relativement volumineux, ces fonctions peuvent s'avérer insuffisantes. Ce qui suit commencera par expliquer les méthodes d'exploitation couramment utilisées lors de la lecture de fichiers volumineux.

Exigences :
Il existe un fichier journal de 800 M avec environ 5 millions de lignes. Utilisez PHP pour renvoyer le contenu des dernières lignes.

Méthode d'implémentation :

1. Utilisez directement la fonction de fichier pour fonctionner
Étant donné que la fonction de fichier lit tout le contenu dans la mémoire en même temps et que PHP est destiné à éviter certains problèmes. programmes écrits Occuper trop de mémoire entraînera une mémoire système insuffisante et provoquera un crash du serveur. Par conséquent, par défaut, l'utilisation maximale de la mémoire est limitée à 16 Mo. Ceci est défini via memory_limit = 16M dans php.ini. -1 , l'utilisation de la mémoire est illimitée.

Ce qui suit est un morceau de code qui utilise file pour extraire la dernière ligne de ce fichier :

<?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;
?>

L'exécution de l'intégralité du code prend 116,9613 (s).
Ma machine dispose de 2 Go de mémoire. Lorsque j'appuie sur F5 pour exécuter, le système devient gris et ne récupère qu'après près de 20 minutes. On voit que les conséquences de la lecture d'un fichier aussi volumineux directement dans la mémoire sont graves, donc. En dernier recours, la limite_mémoire ne peut pas être trop élevée, sinon vous devrez appeler la salle informatique pour réinitialiser la machine.

2. Appelez directement la commande Linux tail pour afficher les dernières lignes
Sous la ligne de commande Linux, vous pouvez directement utiliser tail -n 10 access.log pour afficher facilement les dernières lignes du journal. Vous pouvez directement utiliser PHP pour appeler la commande tail et exécuter le code PHP comme suit :

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

L'exécution complète du code prend 0,0034 (s)

Utiliser directement le fseek de PHP. pour effectuer des opérations sur les fichiers
Cette méthode est la méthode la plus courante. Elle n'a pas besoin de lire tout le contenu du fichier, mais fonctionne directement via des pointeurs, l'efficacité est donc assez efficace. Lorsque vous utilisez fseek pour exploiter des fichiers, il existe de nombreuses méthodes différentes, et l'efficacité peut être légèrement différente. Voici deux méthodes couramment utilisées :

Méthode 1
Recherchez d'abord le fichier via fseek Le dernier EOF, puis trouvez la position de départ de la dernière ligne, récupérez les données de cette ligne, puis trouvez la position de départ de la ligne suivante, puis prenez la position de cette ligne, et ainsi de suite, jusqu'à ce que la ligne $num soit trouvée.
Le code d'implémentation est le suivant

<?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
?>

L'exécution entière du code prend 0,0095 (s)

Méthode 2
Toujours en utilisant fseek pour lire à partir de la fin du fichier, mais cette fois, il ne s'agit pas de lire bit par bit, mais de lire morceau par morceau. Chaque fois qu'une donnée est lue, les données lues sont placées dans un buf, puis le nombre de caractères de nouvelle ligne (\n) est utilisé pour déterminer. s'il a été lu. Complétez les dernières lignes de données de $num.
Le code d'implémentation est le suivant

<?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;
?>

L'exécution entière du code prend 0,0009(s).

Méthode 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));
?>

L'exécution complète du code prend 0,0003(s)

Méthode 4, fonction stream_get_line de PHP, lecture rapide, 500 000 lignes lues Pour les fichiers de données volumineux, cela peut prendre environ 20 secondes ! L'exemple de code est le suivant

$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;
 // } 
 
 }

Recommandations associées :

Explication détaillée des méthodes de série de lecture de fichiers php

Fichier PHP lisant fread, fgets, fgetc, file_get_contents et exemple de code d'utilisation de la fonction de fichier

Une brève introduction à Verrouillage de fichiers PHP et verrouillage de processus

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn