2012-03-26 22 views
7

Me preguntaba si alguien por ahí sabía cómo se podía hacer esto en PHP. Estoy ejecutando un script que implica abrir un archivo, tomar las primeras 1000 líneas, hacer algunas cosas con esas líneas, luego el archivo php abre otra instancia de sí mismo para tomar las siguientes mil líneas y así sucesivamente hasta que llegue al final del archivo . Estoy usando splfileobject para poder buscar una cierta línea, lo que me permite dividirla en mil pedazos de línea bastante bien. El mayor problema que estoy teniendo es con el rendimiento. Estoy lidiando con archivos que tienen más de 10 000 000 de líneas y, si bien las primeras 10 000 líneas son bastante rápidas, hay una gran ralentización exponencial después de ese punto que creo que es solo tener que buscar ese punto.Eliminar las primeras líneas X de un archivo PHP

Lo que me gustaría hacer es leer las primeras mil líneas, luego simplemente eliminarlas del archivo para que mi script siempre lea las primeras mil líneas. ¿Hay alguna manera de hacer esto sin leer el resto del archivo en la memoria? Otras soluciones que he visto implican leer cada línea en una matriz y luego deshacerse de las primeras X entradas, pero con diez millones de líneas que consumirán demasiada memoria y tiempo.

Si alguien tiene una solución u otras sugerencias que podrían acelerar el rendimiento, sería muy apreciado.

+0

¿* piensas * que el tiempo se toma buscando? – salathe

+0

Comenté la línea que itera el contador de línea para que siempre ejecute los primeros 1000 y se ejecutó exponencialmente más rápido.Además, esto se vuelve exponencialmente más lento a medida que avanza, lo único que cambia es la línea que busca. –

+0

La búsqueda no debería tomar * exponencialmente * más tiempo. ¿En qué tipo de escala está la ralentización? – salathe

Respuesta

1

Desafortunadamente no hay una solución real para esto porque los archivos siempre se cargan completamente en la memoria principal antes de que se lean.

Aún así, he publicado esta respuesta porque esta es una posible solución, pero sospecho que apenas mejora el rendimiento. Corrígeme si estoy equivocado.

Puede usar XML para dividir los archivos en unidades de 1000 líneas. Y use DomDocument Class of PHP para recuperar y anexar datos. Puede agregar al niño cuando desee agregar datos y recuperar el primer niño para obtener las primeras mil líneas y eliminar el nodo si lo desea. Al igual que este:

<document> 
    <part> 
     . . . 
     Thousand lines here 
     . . . 
    </part> 
    <part> 
     . . . 
     Thousand lines here 
     . . . 
    </part> 
    <part> 
     . . . 
     Thousand lines here 
     . . . 
    </part> 
    . 
    . 
    . 
</document> 

de otro modo:

Si no está muy seguro de romper las secciones exactamente en 1.000 líneas por qué no lo guarda en una base de datos con cada 1000 en una fila diferente ? Al hacer esto, seguramente reducirá los gastos generales de lectura/escritura de archivos y mejorará el rendimiento.

1

Me parece que el objetivo es analizar una gran cantidad de datos e insertarlos en una base de datos? Si es así, ¿no entiendo por qué es importante trabajar exactamente con 1000 líneas?

Creo que me gustaría abordarlo leyendo una gran cantidad de datos, digamos 1 MB, en la memoria de una vez, y luego escanear hacia atrás desde el final del fragmento en la memoria para la última línea final. Una vez que tengo eso, puedo guardar la posición del archivo y los datos adicionales que tengo (lo que sobra desde el final de la última línea hasta el final del fragmento). Alternativamente, simplemente restablezca el puntero del archivo usando fseek() a donde en el archivo que encontré la última línea que termina, se logra fácilmente con strlen ($ chunk).

De esta manera, todo lo que tengo que hacer es explotar el fragmento ejecutando explode ("\ r \ n", $ chunk) y tengo todas las líneas que necesito, en un bloque adecuadamente grande para su posterior procesamiento.

No se recomienda borrar líneas desde el principio del archivo. Eso va a mezclar una gran cantidad de datos hacia adelante y hacia atrás en el disco.

Cuestiones relacionadas