>백엔드 개발 >PHP 문제 >PHP에서 대용량 파일의 특정 줄을 읽는 방법

PHP에서 대용량 파일의 특정 줄을 읽는 방법

藏色散人
藏色散人원래의
2021-11-16 09:20:532078검색

대형 파일의 특정 줄을 읽기 위해 PHP를 구현하는 방법: 1. 파일 기능을 직접 사용하여 작업합니다. 2. Linux tail 명령을 호출하여 마지막 몇 줄을 표시합니다. 3. PHP의 fseek를 사용하여 파일 작업을 수행합니다. . PHP를 통해 stream_get_line 함수는 읽기를 구현합니다.

PHP에서 대용량 파일의 특정 줄을 읽는 방법

이 기사의 운영 환경: windows7 시스템, PHP7.1 버전, DELL G3 컴퓨터

php 대용량 파일의 특정 줄을 읽는 방법은 무엇입니까?

PHP를 사용하여 대용량 파일을 읽는 다양한 방법 소개

대용량 파일을 읽는 것은 항상 골치 아픈 문제였습니다. 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 Video Tutorial"

위 내용은 PHP에서 대용량 파일의 특정 줄을 읽는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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