14 Stimmen

Wie öffne ich in PHP eine Datei von Zeile X bis Zeile Y?

Das Nächste, was ich in den PHP-Dokumenten gesehen habe, ist das Lesen einer bestimmten Länge mit fread(), aber das legt nicht fest, von welcher Zeile aus zu starten ist. Irgendwelche anderen Vorschläge?

38voto

Gordon Punkte 304254

Ja, das kannst du ganz einfach mit SplFileObject::seek machen

$file = new SplFileObject('filename.txt');
$file->seek(1000);
for($i = 0; !$file->eof() && $i < 1000; $i++) {
    echo $file->current(); 
    $file->next();
}

Das ist eine Methode aus dem SeekableIterator Interface und darf nicht mit fseek verwechselt werden.

Und weil SplFileObject iterierbar ist, kannst du es noch einfacher mit einem LimitIterator machen:

$file = new SplFileObject('longFile.txt');
$fileIterator = new LimitIterator($file, 1000, 2000);
foreach($fileIterator as $line) {
    echo $line, PHP_EOL;
}

Dies ist erneut nullbasiert, also entspricht es den Zeilen 1001 bis 2001.

2 Stimmen

+1 SPL ist sehr schön und könnte mehr Werbung (und Dokumentation) gebrauchen

4 Stimmen

Denken Sie nur daran, dass die SPL-Implementierung auf die gleiche Weise wie die erste vorgeschlagene Lösung implementiert ist. Es wird beginnen, die Datei ab dem ersten Byte zu lesen, eine Zeile nach der anderen, und den Dateizeiger auf die gewünschte Zeile setzen. Es gibt keine Möglichkeit, dieses Problem zu umgehen.

14voto

grom Punkte 15234

Sie werden nicht in der Lage sein, ab Zeile X zu lesen, weil die Zeilen beliebige Längen haben können. Sie müssen also von Anfang an lesen und die Anzahl der gelesenen Zeilen zählen, um zu Zeile X zu gelangen. Zum Beispiel:

= $startLine) {
        echo $line;
    }
    if ($lineNo == $endLine) {
        break;
    }
}
fclose($f);

0 Stimmen

Oder Sie könnten einfach file() und array_slice() verwenden, wie in meiner Antwort :)

1 Stimmen

Ja, außer dass dies die gesamte Datei liest. Dieser Code liest nur das Mindeste, was erforderlich ist.

0 Stimmen

Wird das funktionieren, auch wenn die Datei so groß ist wie die, an der ich derzeit arbeite, die 25MB groß ist?

3voto

Factor Mystic Punkte 25189

Leider müssten Sie zur Lektüre von Zeile x bis Zeile y in der Lage sein, Zeilenumbrüche zu erkennen... und Sie müssten die gesamte Datei durchsuchen. Wenn es jedoch nicht um Leistung geht, können Sie die Zeilen x bis y mit folgendem Code erhalten:

$x = 10; //einschließlich Startzeile
$y = 20; //einschließlich Endzeile
$lines = file('myfile.txt');
$my_important_lines = array_slice($lines, $x, $y);

Siehe: array_slice

0 Stimmen

Du solltest beachten, dass das Array mit 0 beginnt und die Zeilennummerierung normalerweise mit 1 beginnt. Also sollte es ein $x-1, $y-1 oder merke $x=10 ist wirklich $x=11.

3voto

Martin Vseticka Punkte 26325

Nun, du kannst die Funktion fseek nicht verwenden, um die richtige Position zu suchen, weil sie mit einer bestimmten Anzahl von Bytes arbeitet.

Ich glaube, dass es ohne eine Art von Cache oder das Durchgehen der Zeilen nacheinander nicht möglich ist.

4 Stimmen

Was ist mit einem Zeilencache? Speichern Sie irgendwo die Byte-Positionen jeder Zeile und verwenden Sie dann fseek(), um zu ihnen zu gelangen.

0 Stimmen

@christian studer: Sprichst du davon, eine Datei zu indizieren? Das könnte eine interessante Lösung sein, wenn die Datei statisch wäre und sich die meiste Zeit nicht ändern würde. Leider handelt es sich bei den Dateien, die ich lesen werde, um Quellcodedateien, die sich noch in der Entwicklung befinden, also kommt Indizierung nicht in Frage.

1 Stimmen

Ja, indizieren Sie es und speichern Sie den Index im Cache. (Der Zeitstempel auf der Datei könnte anzeigen, ob der zwischengespeicherte Index noch gültig ist). PHP ist überraschend schnell für diese Aufgaben und wenn Sie mehrere Anfragen für dieselbe Datei haben, bevor sie sich erneut ändert, könnte es schnell genug sein, um dies zu bewältigen.

2voto

Sarfraz Punkte 366217

Hier ist die mögliche Lösung :)

= $startLine) {
        echo $line;
    }
    if ($lineNo == $endLine) {
        break;
    }
}
fclose($f);
?>

2 Stimmen

Aber es liest alle Zeilen vor X. Die Frage ist, ob dieser Teil übersprungen werden kann, oder?

0 Stimmen

Sieh dir die Variablen $startLine und $endLine an, es werden nur diese Zeilen gelesen.

1 Stimmen

Die Frage bezieht sich nicht nur auf die Verarbeitung der gegebenen Zeilen (>=startLine && <= endLine). Es geht darum, die Anzahl der Lesevorgänge auf der Festplatte zu minimieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X