2010-05-08 9 views
7

¿Cómo puedo obtener una línea en particular en un archivo de texto de 3 gigas? Las líneas están delimitadas por \ n. Y necesito poder obtener cualquier línea a pedido.Obtener una línea en un archivo enorme con PHP

¿Cómo se puede hacer esto? Solo se necesita devolver una línea. Y no me gustaría utilizar ninguna llamada al sistema.

Nota: Existe la misma pregunta en otros lugares sobre cómo hacer esto en bash. Me gustaría compararlo con el equivalente de PHP.

Actualización: Cada línea tiene la misma longitud durante todo el camino.

+0

Después de actualizar, estaba pensando, quizás usando algún tipo de forma de precalcular y recuperar exactamente los caracteres en el archivo para volver. – JavaRocky

+0

Quiere una base de datos, sin la base de datos. ¿Estás seguro de que no puedes usar una base de datos? –

+0

Quiere leer un archivo sin * ninguna llamada al sistema * ... lo siento pero eso simplemente no es posible. (¿Quiso decir sin usar 'exec' y similares?) – salathe

Respuesta

8

Sin tener algún tipo de índice para el archivo, usted necesita leer todos de la misma hasta que le ha surgido número x de \ n caracteres. Veo que nickf acaba de publicar alguna forma de hacerlo, así que no lo repetiré.

Para hacer esto repetidamente de manera eficiente, tendrá que crear un índice. Guarde algunas posiciones de archivo conocidas para ciertos (o todos) los números de línea una vez, que luego puede usar para buscar la ubicación correcta usando fseek.

Editar: si cada línea tiene la misma longitud, no necesita el índice.

$myfile = fopen($fileName, "r"); 
fseek($myfile, $lineLength * $lineNumber); 
$line = fgets($myfile); 
fclose($myfile); 

El número de línea está 0 en este ejemplo, por lo que es posible que deba restar uno primero. La longitud de línea incluye el carácter \n.

+0

Pero teniendo en cuenta que su archivo es * tan grande *, fseek todavía llevará bastante tiempo, ¿no? – Pacerier

+0

@Pacerier: no, porque no necesita leer todos los datos de principio a fin. Los archivos son de acceso aleatorio. – Thorarin

1

La única manera que puedo pensar para hacerlo sería así:

function getLine($fileName, $num) { 
    $fh = fopen($fileName, 'r'); 

    for ($i = 0; $i < $num && ($line = fgets($fh)); ++$i); 

    return $line; 
} 
0

Si bien esto no es exactamente una solución, ¿cómo es que estás necesitando para sacar una línea de un archivo de texto 3 concierto? ¿El rendimiento es un problema o puede funcionar a un ritmo pausado? Si necesita sacar muchas líneas de este archivo en diferentes momentos, definitivamente sugeriría poner estos datos en un DB de algún tipo. SQLite tal vez sea tu amigo aquí, ya que es muy simple pero no excelente, con muchos scripts/personas accediendo a él al mismo tiempo.

8

Hay poca discusión sobre el problema y no se menciona cómo se debe hacer referencia a 'una línea' (por número, algún valor dentro de ella, etc.), por lo que a continuación solo se adivina qué es falto.

Si no te repugna usar un objeto (podría ser un "nivel demasiado alto", tal vez) y deseas hacer referencia a la línea por desplazamiento, entonces se podría usar SplFileObject (disponible a partir de PHP 5.1.0). Véase el siguiente ejemplo básico:

$file = new SplFileObject('myreallyhugefile.dat'); 
$file->seek(12345689); // seek to line 123456790 
echo $file->current(); // or simply, echo $file 

Ese método en particular (seek) requiere exploración a través del archivo de línea por línea. Sin embargo, si como dices que todas las líneas tienen la misma longitud, entonces puedes usar fseek para llegar a donde quieras ir mucho, mucho más rápido.

$line_length = 1024; // each line is 1 KB line 
$file->fseek($line_length * 1234567); // seek lots of bytes 
echo $file->current(); // echo line 1234568 
Cuestiones relacionadas