kostenloser Webspace werbefrei: lima-city


Datei auslesen ab einer bestimmten bis eine bestimmte zeile

lima-cityForumProgrammiersprachenPHP, MySQL & .htaccess

  1. Autor dieses Themas

    nwage

    nwage hat kostenlosen Webspace.

    Heyo Liebe Community,
    da ich mich nun lange genug hin und her gewälzt habe mit PHP möchte ich meine Kenntnisse bezüglich Dateien etc. verbessern.
    Ich würde gerne wissen (ob) wie es möglich ist bei PHP eine Datei auszulesen ab einer bestimmten Zeile und bis zu einer bestimmten Zeile.

    Ich weiß das man Dateien mit fopen, fread, fgets, file, file_get_contents etc. ausliest, jedoch weiß ich nicht wie man es macht das er ab Zeile xyz anfängt zu Lesen oder bis zu Zeile abc...



    Hoffe ihr konntet mein Problem verstehen u nd könnt mir helfen.


    Lieben Gruß

    €dit: Und lieben gern noch Info ob man abfragen kann ob eine Datei ein Bestimmtes Wort etc. enthält :)

    Beitrag zuletzt geändert: 1.1.2011 22:06:24 von nwage
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. Das ist mit keiner PHP-Methode möglich, aber du kannst mit der Methode file() die Datei zeilenweise in ein Array einlesen und über dieses Array leicht auf die gewünschten Zeilen zugreifen.

    EDIT:
    Du kannst einen String mit der Methode preg_match() nach einer best. Zeichenkette druchsuchen.

    Beitrag zuletzt geändert: 2.1.2011 0:52:37 von metalmachine
  4. Nun eine schöne Frage, deren Antwort ich gerne mal ganz weit ausrollen will, auch wenn hier das Stichwort wie fast immer google ist.

    Allerdings findet man bei google vor allem schlechte weil unperformante Ergebnisse.

    Besser ist da auf jedenfall die PHP-Dokumentation, hier sind alle Funktionen für Dateioperationen interessant, aber speziell für meinen Beitrag sind diese Funktionen wichtig (In den Kommentaren am Ende der Seite sind oft auch sehr gute praxis-Beispiele zu finden):
    file_get_contents
    file
    fopen
    feof
    fgets
    fseek
    fclose

    Aber kommen wir nach der Vorbereitung nun zu der eigentlichen Fragestellung, wie du ja schon weißt kann man mittels
    $file_content = file_get_contents($file_adress);
    die Datei in eine Variable einlesen, diese könnte man nun so in einen Zeilenweisen Array konvertieren:
    $file_content = file_get_contents($file_adress);
    $file_as_array_per_lines = explode("\n", $file_content);
    Da man so alle Zeilen in diesem Array hat könnte man anhand der Indizes jede einzelne Zeile auslesen, die man möchte (Beispiel Zeile 11-20):
    $file_content = file_get_contents($file_adress);
    $file_as_array_per_lines = explode("\n", $file_content);
    for($i=10;$i<19;$i++){
        echo $file_as_array_per_lines[$i] . "\n";
    }
    Das wäre ein einfacher Weg, der aber vom Code her abgekürzt werden kann, hier kommt nun file ins Spiel, den File liest ebenfalls die komplette Datei ein, allerdings gibt die Funktion von sich aus sofort ein Array mit den Zeilen zurück, somit können wir die ersten 2 Zeilen durch die neue Funktion ersetzten:
    $file_as_array_per_lines = file($file_adress);
    for($i=10;$i<19;$i++){
        echo $file_as_array_per_lines[$i];
    }


    So nun sind wir zumindest soweit, dass wir nach bestimmten Zeilen suchen können, aber diese Lösung kann uns nicht gefallen, denn sie schiebt immer die komplette Datei in den Hauptspeicher. Dieser umstand muss früher oder später zu Problemen führen, angenommen der Speicher den PHP nutzen darf ist nur 32 KB groß und die Datei erreicht stattliche 40 KB, dann verabschiedet sich PHP mit einem Fatal error. Diese Situation kann man nur abfangen, indem man nicht die ganze Datei einliest!

    Um die Datei nun nur Teilweise einzulesen benutzen wir fopen zum öffnen und schließen sie mit fclose, da wir in diesem Fall nur einen Filehandle zurück bekommen, mit dem wir dann durch die Datei navigieren müssen und somit nicht die ganze Datei in den Hauptspeicher geschoben wird. Das ist zwar etwas umständlicher (es entsteht auch mehr code), aber um einiges performanter, und so sieht dann unser Grundgerüst aus:
    $file_handle = fopen($file_adress, 'r');
    fclose($file_handle);
    Der 2. Parameter von fopen zeigt an, wofür wir die Datei öffnen wollen und an welcher Stelle der Dateizeiger ($file_handler) positioniert werden soll, in diesem Fall wird die Datei zum lesen geöffnet und der Dateizeiger an den Anfang der Datei gesetzt.

    Nun wollen wir aber wieder versuchen an unsere gesuchten Zeilen zu kommen, dazu können wir die Datei nun ganz einfach mit fgets Zeilenweise einlesen, und dabei einen internen Zähler hochzählen, bis wir unsere gesuchten Zeilen eingelesen haben, das sähe dann z.B. so aus:
    $file_handle = fopen($file_adress, 'r');
    for($i=1; !feof($file_handle); $i++){
        $buffer = fgets($file_handle, 16384);
        if($i > 10 && $i < 21){
            echo $buffer;
        }
    }
    fclose($file_handle);
    Damit hätten wir auf jedenfall schonmal eine performante Lösung (auch wenn ich die for-schleife da schon ziemlich missbrauche) bei der maximal 16384 Bytes in den Speicher geladen werden (dieser Wert ist sinnvoll, da er vor einem Speicherüberlauf schützt und trotzdem auch sehr lange Zeilen zulässt.)
    Genau gesagt, läuft in diesem Codesegment folgendes ab:
    • Es wird eine Datei mit fopen zum lesen geöffnet und der Dateizeiger auf den Anfang der Datei gesetzt;
    • In der for-schleife wird eine Variable $i deklariert, welche nach jedem Durchlauf um 1 hochzählt, als Abbruchbedingung habe ich eine Dateioperation definiert, welche prüft, ob der Dateizeiger am Ende der Datei angekommen ist.
    • In der schleife lade ich eine Zeile der Datei in die Variable $buffer, maximal jedoch 16 KB dabei wird der Dateizeiger automatisch an den Anfang der nächsten Zeile verschoben.
    • Außerdem wird mittels einer kleinen if-Abfrage geprüft, ob wir uns z.Zt. in einer Zeile zwischen 10 und 21 befinden und falls dies zutrifft wird die Zeile, welche ja in $buffer abgelegt ist, ausgegeben.

    So, als letztes will ich noch einmal kurz zeigen, wie du das elendige einlesen von Inhalten, die du gar nicht brauchst auch noch umgehen kannst, denn das dauert ja auch seine Zeit und ist ja eigentlich total unnötig, hier kommen wir nun zu fseek, denn damit können wir den Dateizeiger auch manuell verschieben, allerdings muss man dafür genau wissen an welche Stelle man navigieren möchte, doch dies weiß man selten. Um aber dennoch ein Beispiel zeigen zu können gehe ich einfach mal davon aus, das jede Zeile der Datei genau 128 Byte lang ist (inkl. Zeilenumbruch), denn dann kann ich mir ausrechnen, wo ich hin will, so wie in diesem Beispiel:
    $file_handle = fopen($file_adress, 'r');
    fseek($file_handle, 128*10+1);
    for($i=10; $i--; ){
        $buffer = fgets($file_handle, 16384);
        echo $buffer;
    }
    fclose($file_handle);
    Wie man sieht navigiere ich an den Anfang von Zeile 11 (10 Zeilen, die jeweils 128 Byte lang sind werden übergangen), dann nutze ich eine for-Schleife um 10 zeilen herunter zu zählen um jeweis die Zeile einzulesen und auszugeben. Mehr will ich dazu nicht sagen, da fseek wirklich nicht oft eingesetzt werden kann.

    Falls du noch weitere Fragen hast stell sie einfach, ich antworte gerne.

    Und zu deiner Frage, ob man prüfen kann, ob eine Datei eine bestimmte Zeichenkette enthält würde ich eine Lösung wie diese vorschlagen, da sie ebenfalls performanter ist, als ein regulärer ausdruck:
    $search = "Ein Suchausdruck";
    $file_handle = fopen($file_adress, 'r');
    for($i=1; !feof($file_handle); $i++){
        $buffer = fgets($file_handle, 16384);
        if(strpos($buffer, $search) !== false){
            echo "Die Datei $file_adresse enthält den gesuchten Ausdruck \"$search\".";
            break;
        }
    }
    fclose($file_handle);
    Das kleine Codesegment prüft ganz einfach ob sich in der aktuellen Zeile der Suchausdruck befindet, und meldet das Vorhandensein.

    Diese Methode ist allerdings immer nur auf eine Zeile beschränkt, wenn man über 2 Zeilen suchen will müsste man das etwas umschreiben, so das wir zu folgenden code gelangen würden, den ich aber nicht mehr erläutern will.
    $search = "Ein Suchausdruck mit\nZeilenumbruch";
    $tmp = '';
    $buffer = '';
    $file_handle = fopen($file_adress, 'r');
    for($i=1; !feof($file_handle); $i++){
        $tmp = $buffer;
        $buffer = fgets($file_handle, 16384);
        if(strpos($tmp . $buffer, $search) !== false){
            echo "Die Datei $file_adresse enthält den gesuchten Ausdruck \"$search\".";
            break;
        }
    }
    fclose($file_handle);


    Mit freundlichen Grüßen

    Beitrag zuletzt geändert: 2.1.2011 1:55:41 von nemoinho
  5. Autor dieses Themas

    nwage

    nwage hat kostenlosen Webspace.

    nemoinho schrieb:
    Nun eine schöne Frage, deren Antwort ich gerne mal ganz weit ausrollen will, auch wenn hier das Stichwort wie fast immer google ist.

    Allerdings findet man bei google vor allem schlechte weil unperformante Ergebnisse.

    Besser ist da auf jedenfall die PHP-Dokumentation, hier sind alle Funktionen für Dateioperationen interessant, aber speziell für meinen Beitrag sind diese Funktionen wichtig (In den Kommentaren am Ende der Seite sind oft auch sehr gute praxis-Beispiele zu finden):
    file_get_contents
    file
    fopen
    feof
    fgets
    fseek
    fclose

    Aber kommen wir nach der Vorbereitung nun zu der eigentlichen Fragestellung, wie du ja schon weißt kann man mittels
    $file_content = file_get_contents($file_adress);
    die Datei in eine Variable einlesen, diese könnte man nun so in einen Zeilenweisen Array konvertieren:
    $file_content = file_get_contents($file_adress);
    $file_as_array_per_lines = explode("\n", $file_content);
    Da man so alle Zeilen in diesem Array hat könnte man anhand der Indizes jede einzelne Zeile auslesen, die man möchte (Beispiel Zeile 11-20):
    $file_content = file_get_contents($file_adress);
    $file_as_array_per_lines = explode("\n", $file_content);
    for($i=10;$i<19;$i++){
        echo $file_as_array_per_lines[$i] . "\n";
    }
    Das wäre ein einfacher Weg, der aber vom Code her abgekürzt werden kann, hier kommt nun file ins Spiel, den File liest ebenfalls die komplette Datei ein, allerdings gibt die Funktion von sich aus sofort ein Array mit den Zeilen zurück, somit können wir die ersten 2 Zeilen durch die neue Funktion ersetzten:
    $file_as_array_per_lines = file($file_adress);
    for($i=10;$i<19;$i++){
        echo $file_as_array_per_lines[$i];
    }


    So nun sind wir zumindest soweit, dass wir nach bestimmten Zeilen suchen können, aber diese Lösung kann uns nicht gefallen, denn sie schiebt immer die komplette Datei in den Hauptspeicher. Dieser umstand muss früher oder später zu Problemen führen, angenommen der Speicher den PHP nutzen darf ist nur 32 KB groß und die Datei erreicht stattliche 40 KB, dann verabschiedet sich PHP mit einem Fatal error. Diese Situation kann man nur abfangen, indem man nicht die ganze Datei einliest!

    Um die Datei nun nur Teilweise einzulesen benutzen wir fopen zum öffnen und schließen sie mit fclose, da wir in diesem Fall nur einen Filehandle zurück bekommen, mit dem wir dann durch die Datei navigieren müssen und somit nicht die ganze Datei in den Hauptspeicher geschoben wird. Das ist zwar etwas umständlicher (es entsteht auch mehr code), aber um einiges performanter, und so sieht dann unser Grundgerüst aus:
    $file_handle = fopen($file_adress, 'r');
    fclose($file_handle);
    Der 2. Parameter von fopen zeigt an, wofür wir die Datei öffnen wollen und an welcher Stelle der Dateizeiger ($file_handler) positioniert werden soll, in diesem Fall wird die Datei zum lesen geöffnet und der Dateizeiger an den Anfang der Datei gesetzt.

    Nun wollen wir aber wieder versuchen an unsere gesuchten Zeilen zu kommen, dazu können wir die Datei nun ganz einfach mit fgets Zeilenweise einlesen, und dabei einen internen Zähler hochzählen, bis wir unsere gesuchten Zeilen eingelesen haben, das sähe dann z.B. so aus:
    $file_handle = fopen($file_adress, 'r');
    for($i=1; !feof($file_handle); $i++){
        $buffer = fgets($file_handle, 16384);
        if($i > 10 && $i < 21){
            echo $buffer;
        }
    }
    fclose($file_handle);
    Damit hätten wir auf jedenfall schonmal eine performante Lösung (auch wenn ich die for-schleife da schon ziemlich missbrauche) bei der maximal 16384 Bytes in den Speicher geladen werden (dieser Wert ist sinnvoll, da er vor einem Speicherüberlauf schützt und trotzdem auch sehr lange Zeilen zulässt.)
    Genau gesagt, läuft in diesem Codesegment folgendes ab:
    • Es wird eine Datei mit fopen zum lesen geöffnet und der Dateizeiger auf den Anfang der Datei gesetzt;
    • In der for-schleife wird eine Variable $i deklariert, welche nach jedem Durchlauf um 1 hochzählt, als Abbruchbedingung habe ich eine Dateioperation definiert, welche prüft, ob der Dateizeiger am Ende der Datei angekommen ist.
    • In der schleife lade ich eine Zeile der Datei in die Variable $buffer, maximal jedoch 16 KB dabei wird der Dateizeiger automatisch an den Anfang der nächsten Zeile verschoben.
    • Außerdem wird mittels einer kleinen if-Abfrage geprüft, ob wir uns z.Zt. in einer Zeile zwischen 10 und 21 befinden und falls dies zutrifft wird die Zeile, welche ja in $buffer abgelegt ist, ausgegeben.

    So, als letztes will ich noch einmal kurz zeigen, wie du das elendige einlesen von Inhalten, die du gar nicht brauchst auch noch umgehen kannst, denn das dauert ja auch seine Zeit und ist ja eigentlich total unnötig, hier kommen wir nun zu fseek, denn damit können wir den Dateizeiger auch manuell verschieben, allerdings muss man dafür genau wissen an welche Stelle man navigieren möchte, doch dies weiß man selten. Um aber dennoch ein Beispiel zeigen zu können gehe ich einfach mal davon aus, das jede Zeile der Datei genau 128 Byte lang ist (inkl. Zeilenumbruch), denn dann kann ich mir ausrechnen, wo ich hin will, so wie in diesem Beispiel:
    $file_handle = fopen($file_adress, 'r');
    fseek($file_handle, 128*10+1);
    for($i=10; $i--; ){
        $buffer = fgets($file_handle, 16384);
        echo $buffer;
    }
    fclose($file_handle);
    Wie man sieht navigiere ich an den Anfang von Zeile 11 (10 Zeilen, die jeweils 128 Byte lang sind werden übergangen), dann nutze ich eine for-Schleife um 10 zeilen herunter zu zählen um jeweis die Zeile einzulesen und auszugeben. Mehr will ich dazu nicht sagen, da fseek wirklich nicht oft eingesetzt werden kann.

    Falls du noch weitere Fragen hast stell sie einfach, ich antworte gerne.

    Und zu deiner Frage, ob man prüfen kann, ob eine Datei eine bestimmte Zeichenkette enthält würde ich eine Lösung wie diese vorschlagen, da sie ebenfalls performanter ist, als ein regulärer ausdruck:
    $search = "Ein Suchausdruck";
    $file_handle = fopen($file_adress, 'r');
    for($i=1; !feof($file_handle); $i++){
        $buffer = fgets($file_handle, 16384);
        if(strpos($buffer, $search) !== false){
            echo "Die Datei $file_adresse enthält den gesuchten Ausdruck \"$search\".";
            break;
        }
    }
    fclose($file_handle);
    Das kleine Codesegment prüft ganz einfach ob sich in der aktuellen Zeile der Suchausdruck befindet, und meldet das Vorhandensein.

    Diese Methode ist allerdings immer nur auf eine Zeile beschränkt, wenn man über 2 Zeilen suchen will müsste man das etwas umschreiben, so das wir zu folgenden code gelangen würden, den ich aber nicht mehr erläutern will.
    $search = "Ein Suchausdruck mit\nZeilenumbruch";
    $tmp = '';
    $buffer = '';
    $file_handle = fopen($file_adress, 'r');
    for($i=1; !feof($file_handle); $i++){
        $tmp = $buffer;
        $buffer = fgets($file_handle, 16384);
        if(strpos($tmp . $buffer, $search) !== false){
            echo "Die Datei $file_adresse enthält den gesuchten Ausdruck \"$search\".";
            break;
        }
    }
    fclose($file_handle);


    Mit freundlichen Grüßen

    Recht herzlichen dank, sehr ausführlich :) und beantwortet auch meine Frage ;).
  6. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!