>  기사  >  백엔드 개발  >  PHP의 file 함수와 fseek 함수를 이용한 대용량 파일 읽기의 효율성 비교 분석

PHP의 file 함수와 fseek 함수를 이용한 대용량 파일 읽기의 효율성 비교 분석

高洛峰
高洛峰원래의
2016-12-26 14:12:541550검색

PHP에서는 파일 기능과 fseek 기능을 사용하여 대용량 파일을 읽을 수 있지만 둘 사이에는 효율성에 차이가 있을 수 있습니다. 이 글에서는 대용량 파일 읽기를 수행하기 위한 PHP 파일 기능과 fseek 기능을 비교 분석해 소개하겠습니다. 효율성이 필요한 친구는 참고할 수 있습니다.

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. 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--;
    }// http://www.manongjc.com
    $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)
    {
      // 作者:码农教程  http://www.manongjc.com
      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)

이 글은 여기까지입니다. 내용이 모든 분들의 학습에 도움이 되기를 바라며, 또한 모든 분들이 PHP 중국어 웹사이트를 응원해 주시길 바랍니다.

PHP의 파일함수와 fseek함수를 활용한 대용량 파일 읽기의 효율성 비교분석과 관련된 더 많은 글은 PHP 중국어 홈페이지를 주목해주세요!


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