2008-10-02 27 views
19

fopen falla cuando trato de leer en un archivo de tamaño muy moderado en PHP. A 6 meg file lo hace estrangular, aunque archivos más pequeños alrededor de 100k están bien. He leído que a veces es necesario recompilar PHP con el indicador -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 megas? Finalmente, querremos leer en archivos de alrededor de 100 megas, y sería bueno poder abrirlos y luego leerlos línea por línea con fgets, ya que puedo hacerlo con archivos más pequeños.Lectura de archivos muy grandes en PHP

¿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 bloque de código simple que falla en mi archivo de 6 megas: PHP no parece arrojar un error, simplemente devuelve falso. 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, se hizo llegar a ser algo increíblemente tonto - un problema de permisos. Mi archivo pequeño inexplicablemente había leído permisos cuando el archivo más grande no lo hizo. Doh!

+0

¿Usted apenas está tratando de pasar el archivo a través de? es decir. ¿Descargar? ¿O está realmente analizando los datos en los archivos con algún propósito? Gracias. – DreamWerx

+0

no debería fallar sin generar una advertencia/error. Active todos los errores con error_reporting (E_ALL) y asegúrese de que display_errors esté configurado para mostrarse en su navegador, o consulte el registro de errores de su servidor web. –

Respuesta

36

¿Estás seguro de que es fopen que está fallando y no entorno de tiempo de espera de su guión? El valor predeterminado es generalmente de alrededor de 30 segundos más o menos, y si su archivo tarda más tiempo en leer, es posible que eso suceda.

Otra cosa a considerar puede ser el límite de memoria en su secuencia de comandos: leer el archivo en una matriz puede tropezar con esto, así que revise su registro de errores en busca de advertencias de memoria.

Si ninguno de los anteriores es su problema, puede buscar usando fgets para leer el archivo en línea por línea, procesando sobre 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 producir un error, simplemente devuelve falso.

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

+3

Solo es posible solucionar la forma de abrir archivos realmente grandes. Estoy procesando este archivo de solución de 1.5GB sin ningún problema. Todas las demás soluciones, como file_get_contents of file, leerán todo el archivo en la memoria. Este enfoque se procesa línea por línea. – StanleyD

+0

¿Por qué 4096 significa una línea? – Phoenix

+0

@Phoenix 4096 significa, lea a lo sumo 4096 - 1 bytes si no se encuentran saltos de línea. Verifique el manual. – a3f

0

Bueno, podrías tratar de utilizar la función de lectura de archivos si solo quieres sacar 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

Tenemos que automatizar la adición de grandes conjuntos de datos, de modo que el usuario pueda cargar archivos CSV grandes y la aplicación pueda analizarlos e integrarlos en la base de datos. Me encantaría otras sugerencias de acercamiento si piensas que leer y analizar archivos cargados con PHP no es la mejor manera de hacerlo. –

+0

No creo que PHP tenga un problema con los archivos csv de 6MB? Parece un archivo suficientemente pequeño para que lo maneje. De acuerdo con los comentarios anteriores, publique el error exacto y/o el código. Podría ser un error de memoria su golpear? ¿O un max_execution_time? Necesitamos más información para ayudar. – DreamWerx

1

Utilicé fopen para abrir archivos de video para transmisión, usando una secuencia de comandos php como servidor de transmisión de video, y no tuve problemas con archivos de tamaño superior a 50/60 MB.

0

Si el problema se produce al alcanzar el límite de memoria, puede intentar establecer un valor más alto (esto podría funcionar o no según la configuración de php).

Esto establece el límite de memoria de 12 Mb

ini\_set("memory_limit","12M"); 
+2

Nota: Si bien esto puede ayudar, solo pospone el problema: una vez que llega un archivo de 15 MB en, el problema vuelve. (Si sus archivos nunca superarán un límite determinado, esto puede hacer que el problema desaparezca). – Piskvor

0

para mí, fopen() ha sido muy lento con archivos de más de 1 MB, archivo() es mucho más rápido. Solo tratando de leer las líneas 100 a la vez y crear inserciones por lotes, fopen() tarda 37 segundos frente a archivo() tarda 4 segundos. Debe ser ese paso string-> array integrado en el archivo()

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

5

Hicimos 2 pruebas con un archivo de 1,3 GB y un archivo 9.5GF

1,3

Usando fopen()

Este proceso utiliza 15555 ms para sus cálculos.

Se gastaron 169 ms en llamadas al sistema

Usando file()

Este proceso utiliza 6983 ms para sus cálculos.

Pasó 4469 ms en llamadas al sistema

9.5GB

Usando fopen()

Este proceso utiliza 113559 ms para sus cálculos

gastó 2532 ms en llamadas al sistema

Usando file()

Este proceso utilizado por 8221 ms para sus cálculos

Pasó 7998 ms en el sistema de llamadas

Parece file() es más rápido

Cuestiones relacionadas