2010-05-01 21 views
25

Ok, estoy buscando la manera más rápida posible de leer todos los contenidos de un archivo vía php con un archivo en el servidor, también estos archivos pueden ser enormes. Entonces, es muy importante que le LEA SOLAMENTE lo más rápido posible.La forma más rápida de leer el contenido de un archivo

¿Lo está leyendo línea por línea más rápido que leyendo todo el contenido? Sin embargo, recuerdo haber leído algo sobre esto, que leer todo el contenido puede producir errores para archivos grandes. ¿Es esto cierto?

+0

* (de referencia) * http://www.ibm.com/developerworks/library/os-php-readfiles/ – Gordon

+1

Esta pregunta es un poco antigua, pero para referencia futura, encontré [este sitio] (http://www.raditha.com/wiki/Readfile_vs_include) hace algún tiempo. Analizó varios métodos de lectura de PHP y concluyó que 'readfile()' y 'fpassthru' son los más rápidos, siempre que no requiera ningún procesamiento de ese archivo (es decir, no hay scripts PHP dentro del archivo que deba procesarse). – jmbertucci

+0

Aquí hay varios métodos importantes de PHP para obtener contenido, y probarlos con 'echo microtime' antes de iniciar la función, y después de la función hacer de nuevo' echo microtime' y ver los resultados: http://stackoverflow.com/questions/2176180/get -content-from-a-url-using-php –

Respuesta

33

Si desea cargar el contenido completo de un archivo a una variable de PHP, el más fácil (y, probablemente, más rápido) manera sería file_get_contents.

Pero, si está trabajando con archivos grandes, cargar todo el archivo en la memoria podría no ser una buena idea: probablemente terminará con un error memory_limit, ya que PHP no permitirá que su script use más de (generalmente) un par de mega bytes de memoria.


lo tanto, incluso si no es la solución más rápida, leyendo el archivo línea por línea (fopen + fgets + fclose), y trabajar con esas líneas sobre la marcha, sin tener que cargar todo el archivo en la memoria, podría ser necesario ...

+0

¿Sería una buena idea usar 'SESSIONS' para almacenar esta información, así que no tenemos que seguir abriendo el archivo, si ya se ha abierto una vez? – SoLoGHoST

+3

En primer lugar, las sesiones son * (por defecto) * almacenadas en archivos ;;; entonces, no debe poner Big Data en sesión * (ya que está serializado/no serializado para cada solicitud) * ;;; y almacenar esto en sesiones sería duplicar los datos: cada usuario tiene una sesión diferente ;;; entonces, diría que no, almacenar esto en sesión no es una buena idea. –

+1

Entonces, lo siento, si no estoy entendiendo esto, ¿cree que sería mejor que almacenarlo como una cadena serializada en la base de datos después de leer el archivo (s) línea por línea y de simplemente abrirlo deserializándolo? – SoLoGHoST

5

Usted podría utilizar file_get_contents

Ejemplo:

$homepage = file_get_contents('http://www.example.com/'); 
echo $homepage; 
+0

¿Entonces esto funcionaría para cualquier archivo de tamaño? No importa qué tan grande sea en tamaño de archivo? – SoLoGHoST

+0

@SoLoGHoST: no, también tiene límites de memoria. – Sarfraz

+0

Oh, vale, que esto no es lo que quiero que. Gracias de todos modos. – SoLoGHoST

0

Leer el archivo completo de una vez es más rápido.

Pero los archivos enormes pueden consumir toda su memoria y causar problemas. Entonces su apuesta más segura es leer línea por línea.

8
$file_handle = fopen("myfile", "r"); 
while (!feof($file_handle)) { 
    $line = fgets($file_handle); 
    echo $line; 
} 
fclose($file_handle); 
  1. Abrir el archivo y lo almacena en $file_handle como referencia para el propio archivo.
  2. Compruebe si ya se encuentra al final del archivo.
  3. Siga leyendo el archivo hasta que esté al final, imprimiendo cada línea a medida que la lee.
  4. Cierra el archivo.
+0

Leer una línea a la vez puede no ser muy óptimo si el archivo tiene líneas muy cortas. Leer en trozos de un tamaño específico podría funcionar mejor – GordonM

14

file_get_contents() es la forma más optimizada para leer archivos en PHP, sin embargo - ya que estás leyendo los archivos en la memoria que siempre está limitado a la cantidad de memoria disponible.

Puede emitir un ini_set('memory_limit', -1) si tiene los permisos adecuados, pero igual estará limitado por la cantidad de memoria disponible en su sistema, esto es común en todos los lenguajes de programación.

La única solución es leer el archivo en trozos, para que pueda utilizar file_get_contents() con los argumentos cuarto y quinto ($offset y $maxlen - se especifica en bytes):

string file_get_contents(string $filename[, bool $use_include_path = false[, resource $context[, int $offset = -1[, int $maxlen = -1]]]]) 

Aquí está un ejemplo donde utilizo esta técnica para servir archivos de descarga grandes:

public function Download($path, $speed = null) 
{ 
    if (is_file($path) === true) 
    { 
     set_time_limit(0); 

     while (ob_get_level() > 0) 
     { 
      ob_end_clean(); 
     } 

     $size = sprintf('%u', filesize($path)); 
     $speed = (is_int($speed) === true) ? $size : intval($speed) * 1024; 

     header('Expires: 0'); 
     header('Pragma: public'); 
     header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
     header('Content-Type: application/octet-stream'); 
     header('Content-Length: ' . $size); 
     header('Content-Disposition: attachment; filename="' . basename($path) . '"'); 
     header('Content-Transfer-Encoding: binary'); 

     for ($i = 0; $i <= $size; $i = $i + $speed) 
     { 
      ph()->HTTP->Flush(file_get_contents($path, false, null, $i, $speed)); 
      ph()->HTTP->Sleep(1); 
     } 

     exit(); 
    } 

    return false; 
} 

Otra opción es el uso de los archivos s optimizado fopen(), feof(), fgets() y fclose() funciones, especialmente si se preocupan por conseguir líneas enteras a la vez, aquí es another example I provided in another StackOverflow question for importing large SQL queries into the database:

function SplitSQL($file, $delimiter = ';') 
{ 
    set_time_limit(0); 

    if (is_file($file) === true) 
    { 
     $file = fopen($file, 'r'); 

     if (is_resource($file) === true) 
     { 
      $query = array(); 

      while (feof($file) === false) 
      { 
       $query[] = fgets($file); 

       if (preg_match('~' . preg_quote($delimiter, '~') . '\s*$~iS', end($query)) === 1) 
       { 
        $query = trim(implode('', $query)); 

        if (mysql_query($query) === false) 
        { 
         echo '<h3>ERROR: ' . $query . '</h3>' . "\n"; 
        } 

        else 
        { 
         echo '<h3>SUCCESS: ' . $query . '</h3>' . "\n"; 
        } 

        while (ob_get_level() > 0) 
        { 
         ob_end_flush(); 
        } 

        flush(); 
       } 

       if (is_string($query) === true) 
       { 
        $query = array(); 
       } 
      } 

      return fclose($file); 
     } 
    } 

    return false; 
} 

la técnica que utilice realmente va a depender de lo que estamos tratando de hacer (como puede ver con la función de importación de SQL y la función de descarga), pero siempre tendrá que leer los datos en los trozos.

0

Si no está preocupado por la memoria y el tamaño del archivo,

$lines = file($path); 

$ líneas es entonces la matriz del archivo.

+0

que creo que es solo un preg_split (/ \ r? \ N? /, File_get_contents()) – ppostma1

-2

Puede probar cURL (http://php.net/manual/en/book.curl.php).

Altho Es posible que desee comprobar, tiene sus límites, así

$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, "http://example.com/"); 
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); 
$data = curl_exec ($ch); // Whole Page As String 
curl_close ($ch); 
+2

¿Alguna razón para escribir en mayúscula la primera letra de cada palabra? – developerbmw

1
foreach (new SplFileObject($filepath) as $lineNumber => $lineContent) { 

    echo $lineNumber."==>".$lineContent; 
    //process your operations here 
} 
Cuestiones relacionadas