Lectura de archivos muy grandes en PHP


fopen está fallando cuando intento leer en un archivo de tamaño muy moderado en PHP. A 6 meg file lo atraganta, aunque los archivos más pequeños alrededor de 100k están bien. he leído que a veces es necesario recompilar PHP con la bandera -D_FILE_OFFSET_BITS=64 para leer archivos de más de 20 gigas o algo ridículo, pero ¿no debería tener problemas con un archivo de 6 meg? Con el tiempo vamos a querer leer en archivos que son de alrededor de 100 megas, y sería bueno ser capaz de abrirlos y luego leer a través de ellos línea por línea con fgets como soy capaz de hacer con archivos más pequeños.

¿Cuáles son sus trucos/soluciones para leer y hacer operaciones en archivos muy grandes en PHP?

Actualización: Aquí hay un ejemplo de un simple codeblock que falla en mi archivo 6 meg - PHP no parece lanzar un error, solo devuelve false. ¿Tal vez estoy haciendo algo extremadamente tonto?

$rawfile = "mediumfile.csv";

if($file = fopen($rawfile, "r")){  
  fclose($file);
} else {
  echo "fail!";
}

Otra actualización: Gracias a todos por su ayuda, resultó ser algo increíblemente tonto - un problema de permisos. Mi pequeño archivo inexplicablemente tenía permisos de lectura cuando el archivo más grande no. Doh!

Author: Alive to Die, 2008-10-02

8 answers

¿Está seguro de que es fopen lo que está fallando y no la configuración de tiempo de espera de su script? El valor predeterminado es generalmente alrededor de 30 segundos o así, y si su archivo está tomando más tiempo que eso para leer, puede estar disparando eso.

Otra cosa a considerar puede ser el límite de memoria en su script - leer el archivo en una matriz puede tropezar con esto, así que revise su registro de errores para ver si hay advertencias de memoria.

Si ninguno de los anteriores son su problema, puede buscar el uso de fgets to leer el archivo línea por línea, procesamiento de la marcha.

$handle = fopen("/tmp/uploadfile.txt", "r") or die("Couldn't get handle");
if ($handle) {
    while (!feof($handle)) {
        $buffer = fgets($handle, 4096);
        // Process buffer here..
    }
    fclose($handle);
}

Editar

PHP no parece generar un error, solo devuelve false.

¿La ruta a $rawfile es correcta en relación con el lugar donde se ejecuta el script? Tal vez intente establecer una ruta absoluta aquí para el nombre del archivo.

 40
Author: ConroyP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 13:29:17

Hizo 2 pruebas con un archivo de 1.3 GB y un archivo de 9.5 GB.

1.3 GB

Usando fopen()

Este proceso utiliza 15555 ms para sus cálculos.

Gastó 169 ms en llamadas al sistema.

Usando file()

Este proceso utilizó 6983 ms para sus cálculos.

Gastó 4469 ms en llamadas al sistema.

9.5 GB

Usando fopen()

Este proceso utilizó 113559 ms para sus cálculos.

Se gastó 2532 ms en llamadas al sistema.

Usando file()

Este proceso utilizó 8221 ms para sus cálculos.

Gastó 7998 ms en llamadas al sistema.

Parece file() es más rápido.

 7
Author: Al-Punk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-21 00:11:17

Utilicé fopen para abrir archivos de video para streaming, usando un script php como servidor de streaming de video, y no tuve ningún problema con archivos de tamaño superior a 50/60 MB.

 1
Author: Enrico Murru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 13:21:46

Bien, podría intentar usar la función readfile si solo desea generar el archivo.

Si este no es el caso, tal vez debería pensar en el diseño de la aplicación, ¿por qué desea abrir archivos tan grandes en las solicitudes web?

 0
Author: Fionn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 13:16:57

Si el problema es causado por golpear el límite de memoria, puede intentar establecer un valor más alto (esto podría funcionar o no dependiendo de la configuración de php).

Esto establece el límite de memoria a 12 Mb

ini\_set("memory_limit","12M");
 0
Author: Juan Pablo Califano,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-13 06:45:12

Para mí, fopen() ha sido muy lento con archivos de más de 1mb, file() es mucho más rápido.

Simplemente tratando de leer las líneas 100 a la vez y crear inserciones por lotes, fopen() toma 37 segundos frente a file() toma 4 segundos. Debe ser ese string->array paso incorporado en file()

Probaría todas las opciones de manejo de archivos para ver cuál funcionará mejor en su aplicación.

 0
Author: RightClick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-11 05:30:25

No estoy seguro de si ha resuelto el problema. También estaba tratando de procesar un archivo grande mientras me encontré con un sitio web que creo que podría ser la respuesta.

Usando el comando yield.

Https://www.sitepoint.com/performant-reading-big-files-php /

 0
Author: Dean Chiu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-03 15:40:02
 -1
Author: Ólafur Waage,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 13:28:44