2010-08-27 26 views
14

Tengo un script que analiza archivos grandes línea por línea. Cuando encuentra un error que no puede manejar, se detiene, notificándonos la última línea analizada.fseek() por línea, no bytes?

¿Es esta la mejor/única forma de buscar una línea específica en un archivo? (. fseek() no es utilizable en mi caso)

<?php 

for ($i = 0; $i < 100000; $i++) 
    fgets($fp); // just discard this 

no tengo un problema con esto, es lo suficientemente rápido - sólo se siente un poco sucia. Por lo que sé sobre el código subyacente, no creo que haya una mejor manera de hacerlo.

Respuesta

30

Una manera fácil de buscar a una línea específica en un archivo es utilizar la clase SplFileObject, que apoya la búsqueda de un número de línea (seek()) o desplazamiento de bytes (fseek())

$file = new SplFileObject('myfile.txt'); 
$file->seek(9999);  // Seek to line no. 10,000 
echo $file->current(); // Print contents of that line 

En el fondo, seek() simplemente hace lo que hizo su código PHP (excepto, en código C).

+0

¡Agradable! Encontré esto hace un tiempo y comencé a usarlo. – jasonbar

+0

En este caso, seek leerá directamente la línea 10,000, sin caminar a través de las líneas 1 - 9,999 para alcanzar la línea dada? – Googlebot

+0

@ Ali: no, ¿cómo crees que sabe dónde comienzan las líneas? Lee a través del archivo. Existen otras alternativas si desea buscar directamente una línea, pero involucran sistemas potencialmente complejos para realizar un seguimiento de dónde comienzan las líneas en el archivo. – salathe

4

Si solo tiene el número de línea para continuar, no hay otro método para encontrar la línea. Los archivos no se basan en líneas (o incluso en caracteres), por lo que no hay forma de simplemente saltar a una línea específica en un archivo.

Puede haber otras formas de leer las líneas del archivo que podrían ser ligeramente más rápidas, como leer fragmentos más grandes del archivo en un búfer y leer líneas de eso, pero solo podría esperar que sea un pequeño porcentaje Más rápido. Cualquier método para encontrar una línea específica en un archivo todavía tiene que leer todos los datos hasta esa línea.

+0

Sí, pensé que sí. De alguna manera, pensé que un buen 'fseekbyline()' que fuera solo un envoltorio para el código C me haría sentir mejor. heh. – jasonbar

0

Si entiendo correctamente, desea buscar la línea específica en algún momento después de haber encontrado un error. Si ese es el caso, probablemente almacene o imprima el número de línea de la línea incorrecta en algún lugar, dependiendo de lo que quiera decir con "notificar".

A menos que realmente significa que no se puede utilizar fseek() *, lo que puede hacer es también tienda/imprimir la posición en el archivo donde comienza la línea malo. Entonces puedes fseek().

* ¿Cómo, en ese caso, se podría usar fseekbyline() si existiera?

2

Sé que es tarde para publicar pero puede ayudar a algunos PPL hice una función como fseekbyline un día ...

function GoToLine($handle,$line) 
{ 
    fseek($handle,0); // seek to 0 
    $i = 0; 
    $bufcarac = 0;      

    for($i = 1;$i<$line;$i++) 
    { 
    $ligne = fgets($handle); 
    $bufcarac += strlen($ligne); // in the end bufcarac will contains all caracters until the line 
    } 

    fseek($handle,$bufcarac); 
} 

no existe un sistema de error, si quieres ir a la línea < 1 o 203 pero el archivo está vacío ... no obtendrá nada bueno.

mismo si quieres ir fuera del EOT

+0

Para cuando PHP haya pasado por el ciclo for, el puntero estará donde usted lo haya deseado.Simplemente llamando a fgets ($ handle) es suficiente para poner en el bucle for, y puede evitar la carga de memoria en las variables $ bufcarac y $ ligne. – Gregory

1
rewind($handle); 
while($i=0; $i<$desired_line; i++) 
    fgetcsv($handle, 1000, ",") 

Esto funciona para mí mientras tengo que rebobinar una línea específica varias veces en mi secuencia de comandos.

No estoy seguro de si esto consume memoria o velocidad, pero funciona.

+0

Esto es corto y al grano. Aunque fgetcsv es específico para archivos CSV en lugar de cualquier archivo de texto. Al menos es útil para mí. – Gregory

Cuestiones relacionadas