>  기사  >  백엔드 개발  >  PHP가 대용량 파일을 효율적으로 읽는 방법에 대한 예 비교

PHP가 대용량 파일을 효율적으로 읽는 방법에 대한 예 비교

*文
*文원래의
2017-12-29 18:59:442122검색

큰 파일을 읽는 것은 항상 골치 아픈 일이었습니다. PHP를 사용하여 작은 파일을 개발하고 읽는다면 이를 달성하기 위해 다양한 기능을 직접 사용할 수 있습니다. 그러나 일단 큰 문서에 도달하면 일반적으로 사용되는 방법으로는 불가능하다는 것을 알게 됩니다. 정상적으로 사용되거나 너무 오래 걸리고 너무 막히게 됩니다. PHP에서 대용량 파일을 읽는 문제에 대한 해결책을 살펴보겠습니다. 이것이 모든 사람에게 도움이 되기를 바랍니다.

PHP에서 파일을 읽을 때 가장 빠른 방법은 file 및 file_get_contents와 같은 일부 기능을 사용하는 것입니다. 몇 줄의 간단한 코드로 필요한 기능을 아름답게 완성할 수 있습니다. 그러나 운용 중인 파일이 상대적으로 큰 파일인 경우에는 이러한 기능이 충분하지 않을 수 있습니다. 다음은 대용량 파일을 읽을 때 일반적으로 사용되는 조작 방법을 설명하기 위한 요구 사항부터 시작합니다.

요구 사항:
약 500만 줄의 800M 로그 파일이 있습니다. PHP를 사용하여 마지막 몇 줄의 내용을 반환하세요.

구현 방법:

1. 파일 함수를 직접 사용하여 작동
파일 함수는 모든 내용을 한 번에 메모리로 읽어들이기 때문에 PHP는 잘못 작성된 일부 프로그램이 너무 많은 메모리를 차지하여 시스템 메모리가 부족해지는 것을 방지합니다. , 서버 충돌을 유발하므로 기본적으로 최대 메모리 사용량은 16M로 제한됩니다. 이는 php.ini에서 memory_limit = 16M을 통해 설정됩니다. 이 값을 -1로 설정하면 메모리 사용량이 제한되지 않습니다.

다음은 file을 사용하여 이 파일의 마지막 줄을 추출하는 코드입니다.

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

 전체 코드를 실행하는 데 116.9613(s)이 걸립니다.
 내 컴퓨터의 메모리는 2G입니다. F5를 눌러 실행하면 시스템이 회색으로 바뀌고 거의 20분 후에야 복구됩니다. 이렇게 큰 파일을 메모리에 직접 읽어 들이면 결과가 매우 심각하다는 것을 알 수 있습니다. 아니요, memory_limit를 너무 높게 설정할 수 없습니다. 그렇지 않은 경우 유일한 옵션은 컴퓨터실에 전화하여 시스템을 재설정하는 것입니다.

2. Linux tail 명령을 직접 호출하여 마지막 몇 줄을 표시합니다.
Linux 명령줄에서 tail -n 10 access.log를 직접 사용하여 로그 파일의 마지막 몇 줄을 쉽게 표시할 수 있습니다. PHP에서 tail 명령을 호출하려면 다음과 같이 PHP 코드를 실행하세요.

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

전체 코드 실행에는 0.0034(s)

3이 소요됩니다. PHP의 fseek를 직접 사용하여 파일 작업을 수행하세요.
이 방법은 가장 일반적인 방법입니다. 파일의 모든 내용을 요구하지 않고 내용을 읽는 대신 포인터를 통해 직접 동작하므로 효율성이 상당히 효율적입니다. fseek를 사용하여 파일을 조작하는 방법은 여러가지가 있으며 효율성이 약간 다를 수 있습니다. 다음은 일반적으로 사용되는 두 가지 방법입니다.

방법 1
 먼저 fseek를 통해 파일의 마지막 EOF를 찾은 다음 시작 부분을 찾습니다. 마지막 행의 위치, 이 행의 데이터를 가져온 다음 다음 행의 시작 위치를 찾은 다음 $num 행을 찾을 때까지 이 행의 위치를 ​​가져오는 식으로 계속됩니다.
구현 코드는 다음과 같습니다

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

 전체 코드 실행에 0.0095(s)가 걸립니다

방법 2
 파일 끝부터 읽기 위해 여전히 fseek를 사용하지만 이번에는 비트 단위로 읽지 않고, 그러나 하나씩 읽는 방식에서는 데이터 조각을 읽을 때마다 읽은 데이터가 buf에 배치된 다음 개행 문자(\n)의 수를 사용하여 데이터의 마지막 $num 행이 읽혀졌는지 여부를 결정합니다. 읽다.
구현 코드는 다음과 같습니다

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

전체 코드 실행에는 0.0009(s)가 소요됩니다.

방법 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));
?>

전체 코드 실행 시간은 0.0003(s)

방법 4인 PHP의 stream_get_line 함수는 빠르게 읽어 들이고, 500,000개의 데이터가 담긴 대용량 파일을 읽는 데 20초 정도 걸립니다! 예제 코드는 다음과 같습니다

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

관련 권장 사항:

php 파일 읽기 시리즈 방법 자세한 설명

PHP 파일 읽기 fread, fgets, fgetc, file_get_contents 및 파일 기능 사용 예제 코드

PHP 파일 잠금 및 프로세스 잠금에 대한 간략한 소개

위 내용은 PHP가 대용량 파일을 효율적으로 읽는 방법에 대한 예 비교의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.