Maison  >  Article  >  développement back-end  >  Explications détaillées et exemples de diverses méthodes de lecture de fichiers volumineux en PHP

Explications détaillées et exemples de diverses méthodes de lecture de fichiers volumineux en PHP

墨辰丷
墨辰丷original
2018-06-04 10:20:091717parcourir

Cet article présente principalement en détail les différentes méthodes de lecture de gros fichiers en PHP. Les amis intéressés peuvent s'y référer

La lecture de gros fichiers a toujours été un casse-tête. Nous utilisons PHP pour développer pour lire de petits fichiers. être implémenté directement à l'aide de diverses fonctions. Cependant, une fois que vous aurez accédé à un article volumineux, vous constaterez que les méthodes couramment utilisées ne peuvent pas être utilisées normalement ou prennent trop de temps et sont trop bloquées. Examinons le problème de la lecture de fichiers volumineux. Solution PHP, j'espère que l'exemple pourra vous aider.

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 complète du code a pris 116,9613 (s).
Ma machine dispose de 2 Go de mémoire. Lorsque j'appuie sur F5 pour exécuter, le système devient directement gris et récupère après presque 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 de 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 entière du code prend 0,0034 (s)

3 . Utilisez directement 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, son efficacité est donc élevée. 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 La méthode fseek commence la lecture à partir de la fin du fichier, mais cette fois, elle ne lit pas bit par bit, mais lit morceau par morceau. Chaque fois qu'une donnée est lue, les données lues sont placées dans un buf, et. puis le caractère de nouvelle ligne est utilisé (\n) pour déterminer si les dernières lignes de données $num ont été lues.
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 entière du code prend 0,0003(s)

Méthode 4, PHP Le stream_get_line La fonction lit rapidement. Il faut environ 20 secondes pour lire un gros fichier de données contenant 500 000 éléments ! 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;
 // } 
 
 }

Résumé : Ce qui précède est l'intégralité du contenu de cet article, j'espère qu'il sera utile à l'apprentissage de chacun.

Recommandations associées :

Explication détaillée de l'héritage et exemples d'utilisation des classes en PHP

Comment implémenter la fonction d'affichage de pagination de données en PHP

phpPlusieurs façons d'obtenir le chemin physique du répertoire racine du site Web

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