Datei auslesen und speziell ausgeben

Ensaw

Mitglied
Hallo,

ich stehe gerade vor einem Problem. Ich habe eine .txt Datei, die 16.000 Einträge hat.

Jeder "Satz" sieht genau gleich aus:

[23.04.2014 14:26:23] Ensaw: Dies ist ein beispiel Text

Ich möchte die Datei auslesen lassen, was ja auch einfach geht.

PHP:
$datei = "text.txt";
$oeffnen = fopen($datei, "r");
$ausgeben = fread($oeffnen, filesize($datei));

Nun hat die Varialbe $ausgeben die Komplette Datei. Wie kann ich nun "[23.04.2014 14:26:23]", "Ensaw:" und "Dies ist ein beispiel Text" in diese Variablen aufteilen?

Die nachfolgenen Zeilen sind unterschiedlich lang.
Außer die Zeichen zwischen den "[" und "]". Dort sind immer genau 19 Zeichen.
 
Mit Regulären Ausdrücken: preg_match_all()
Ist das eine Zeile? Oder mit was wird der Text abgeschlossen?

Wenn ja:

mit file_get_contents() das ganze File in ein String lesen.
mit dem Pattern '/\[(.{19})\] ([[:alpha:]]+): (.*)$/im' und preg_match_all alles auswerten. Fertig
Hab da mal ein Versuch: http://regexp-evaluator.de/evaluator/c222811d714c79e322aa9ff9bc809193/#ergebnis

Teststring:
Code:
[23.04.2014 14:26:23] Ensaw: Dies ist ein beispiel Text 
[23.04.2014 14:26:24] Bsaw: Wie gehts
[23.04.2014 14:26:27] Hallo: Das Wetter ist schön

PHP-Code
PHP:
//Datei einlesen
$subject = file_get_contents("text.txt");
//Pattern setzen
$pattern = '/\[(.{19})\] ([[:alpha:]]+): (.*)$/im';
//Text auswerten
$anzTreffer= preg_match_all($pattern, $subject, $subpattern, PREG_SET_ORDER);
//Auswertung ausgeben
echo '<pre>'.print_r($subpattern, TRUE).'</pre>';

Und das Resultat:
Code:
Array
(
    [0] => Array
        (
            [0] => [23.04.2014 14:26:23] Ensaw: Dies ist ein beispiel Text 
            [1] => 23.04.2014 14:26:23
            [2] => Ensaw
            [3] => Dies ist ein beispiel Text 
        )
    [1] => Array
        (
            [0] => [23.04.2014 14:26:24] Bsaw: Wie gehts
            [1] => 23.04.2014 14:26:24
            [2] => Bsaw
            [3] => Wie gehts
        )
    [2] => Array
        (
            [0] => [23.04.2014 14:26:27] Hallo: Das Wetter ist schön
            [1] => 23.04.2014 14:26:27
            [2] => Hallo
            [3] => Das Wetter ist schön
        )
)
 
Genau so hatte ich es mir vorgestellt. Klappt auch soweit alles, außer, dass wenn ein Text nen Zeilenumbruch hat, der Text nach dem Zeilenumbruch nicht angezeigt wird.

Code:
[23.04.2014 14:26:23] Ensaw: Dies ist ein beispiel Text 
[23.04.2014 14:26:24] Bsaw: Wie geht

es dir heute?

Und wie findest du das Wetter?
[23.04.2014 14:26:27] Ensaw: Das Wetter ist schön

PHP:
Array
(
    [0] => Array
        (
            [0] => [23.04.2014 14:26:23] Ensaw: Dies ist ein beispiel Text 
            [1] => 23.04.2014 14:26:23
            [2] => Ensaw
            [3] => Dies ist ein beispiel Text 
        )
    [1] => Array
        (
            [0] => [23.04.2014 14:26:24] Bsaw: Wie gehts
            [1] => 23.04.2014 14:26:24
            [2] => Dupla
            [3] => Wie geht
        )
    [2] => Array
        (
            [0] => [23.04.2014 14:26:27] Hallo: Das Wetter ist schön
            [1] => 23.04.2014 14:26:27
            [2] => Ensaw
            [3] => Das Wetter ist schön
        )
)
 
Zurück zu meiner Frage: Wie definerst du das Textende?

Anderst gefragt. Kann im text selber ein [ vorkommen?

Nachtrag:
Wenn ja, dann versuchs mal mit dieem Pattern:
Code:
'/\[([\.\d :]{19})\] ([[:alpha:]]+): ((?:.(?!\[([\.\d :]{19})\]))*)/sm'

Achja, und versuch den Pattern nachzuvollziehen oder frag (wenn dus nicht selber herausfindest), was das genau bewirken soll. Nur so lernt man dazu...

http://regexp-evaluator.de/evaluator/fb683aebc603c434b53f82f2edde36fa/#ergebnis
 
Und falls die 16.000 Einträge zu viel für das Memory-Limit sind, hier eine etwas resourcen-schonendere Alternative, die auch umgebaut werden kann, so das immer nur ein Datensatz im Speicher ist:

PHP:
<?php
// Datei öffnen
$fd = fopen("test.txt", "r");

// Puffer vorbereiten
$entries = array();

if ($fd)
{
  // Puffer initialisieren
  $text = $time = $tag = null;
  while (! feof($fd) ) // Solange das Ende der Datei nicht erreicht ist
  {
    $line = fgets($fd, 1024); // Zeile holen

    if ($line[0] == '[') // Prüfen, ob es eine Zeile mit Zeit-Tag am Anfang ist
    {
      // Wenn alles gefunden wurde, fügen wir den Eintrag in das Array - statt dessen könnte es auch direkt ausgegeben werden
      if($text && $tag && $time)
      {
        $entries[] = array('time' => $time, 'tag' => $tag, 'text' => trim($text));
      }
      // Suche Ende des Zeit-Felds
      $endTime = strpos( $line, ']' );
      // Suche Ende des Tag-Felds
      $endTag = strpos( $line, ':', $endTime + 2);
      // Ende des Tag-Felds ist gleichzeit Start des Textes
      $startText = $endTag + 2;

      // Zeit-Feld extrahieren
      $time = substr($line, 1, $endTime - 1);
      // Tag-Feld extrahieren
      $tag = substr($line, $endTime + 2, $endTag - $endTime - 2);
      // Text-Feld extrahieren
      $text = substr($line, $startText);
    }
    else
    {
      // Text-Ende wurde noch nicht gefunden, also an Text-Feld anhängen
      $text .= $line;
    }
  }

  // Letzten Eintrag einfügen, oder ausgeben, was auch immer...
  if($text && $tag && $time)
  {
    $entries[] = array('time' => $time, 'tag' => $tag, 'text' => trim($text));
  }
  // Fertig - Datei schließen
  fclose($fd);
}

// Debugging....
var_dump($entries);

Denn man hat von allen Einträgen immer mehrere Versionen im Speicher, wenn man file_get_contents() und anschließend noch preg_match_all macht. Da wird das Memory-Limit schnell zu Gefahr bei so einer großen Anzahl an Zeilen.

EDIT: Was ich noch anmerken wollte: mit dieser Version ist das Ende des Textes automatisch festgelegt, nämlich das '[' am Anfang der Zeile. Wenn dein Text auch ein das haben sollte, müssten die Prüfungen erweitert werden.
 
Zuletzt bearbeitet:
Ich bedanke mich bei euch 2.

@Yaslaw: Bei regulären Ausdrücken bin ich selbst noch nicht der Profi, aber ich verstehe, was du dort angegeben hast. Vielen Dank für deine Mühe!

@saftmeister: Deine Methode funktioniert einwandfrei, genau wie die von Yaslaw. Vielen Dank!

Ihr habt mir sehr geholfen.
 

Neue Beiträge

Zurück