Bitte warten...

PHP: Dateien und Ordner

Eine Datei erzeugen

Um eine beliebige Datei zu erzeugen, sie zu lesen oder in sie zu schreiben, muss für diese Datei mit fopen() ein Stream geöffnet werden. Als zweiten Parameter von fopen() können folgende Kurzzeichen angegeben werden:

– Öffnen zum Lesen. Dateizeiger an den Anfang.
r+ – Öffnen zum Lesen und Schreiben. Dateizeiger an den Anfang.
– Öffnen zum Schreiben. Dateizeiger an den Anfang. Erzeugt neue Datei.
w+ – Öffnen zum Lesen und Schreiben. Dateizeiger an den Anfang. Erzeugt neue Datei.
– Öffnen zum Schreiben. Dateizeiger ans Ende. Erzeugt neue Datei.
a+ – Öffnen zum Lesen und Schreiben. Dateizeiger ans Ende. Erzeugt neue Datei.

Zum Schreiben in eine Datei wird die Funktion fwrite() verwendet. Dazu müssen für das aktuelle Verzeichnis Schreibrechte bestehen.
Nach der gewünschten Aktion muss der Stream mit fclose() wieder geschlossen werden.

Anmerkung: Will man eine Datei ohne Inhalt anlegen, kann man die Funktion touch($file) verwenden (ohne fopen()).

Im folgenden Beispiel wird der String $data mit base64_decode() in einen dekodierten Datenstrom umgewandelt und in die Datei test.rtf geschrieben. Anschließend wird ein Link erzeugt, um die Datei herunterzuladen bzw. zu öffnen.

Code kopieren
<?php
  $data = trim("e1xydGYxXGFuc2lcZGVmZjBcYWRlZmxhbmcxMDI1CntcZm9udHRibHtcZjBcZnJvbWFuXGZw
cnEyXGZjaGFyc2V0MCBEZWphVnUgU2Fuczt9e1xmMVxmcm9tYW5cZnBycTJcZmNoYXJzZXQw
IERlamFWdSBTYW5zO317XGYyXGZzd2lzc1xmcHJxMlxmY2hhcnNldDAgRGVqYVZ1IFNhbnM7
fXtcZjNcZm5pbFxmcHJxMlxmY2hhcnNldDAgRGVqYVZ1IFNhbnM7fX0Ke1xjb2xvcnRibDtc
cmVkMFxncmVlbjBcYmx1ZTA7XHJlZDEyOFxncmVlbjEyOFxibHVlMTI4O30Ke1xzdHlsZXNo
ZWV0e1xzMVxjZjB7XCpcaHlwaGVuMlxoeXBobGVhZDJcaHlwaHRyYWlsMlxoeXBobWF4MH1c
cnRsY2hcYWYzXGFmczI0XGxhbmcyNTVcbHRyY2hcZGJjaFxhZjNcbGFuZ2ZlMjU1XGhpY2hc
ZjBcZnMyNFxsYW5nMTAzMVxsb2NoXGYwXGZzMjRcbGFuZzEwMzFcc25leHQxIE5vcm1hbDt9
CntcczJcc2IyNDBcc2ExMjBca2VlcG5cY2Ywe1wqXGh5cGhlbjJcaHlwaGxlYWQyXGh5cGh0
cmFpbDJcaHlwaG1heDB9XHJ0bGNoXGFmczI4XGxhbmcyNTVcbHRyY2hcZGJjaFxsYW5nZmUy
NTVcaGljaFxmMlxmczI4XGxhbmcxMDMxXGxvY2hcZjJcZnMyOFxsYW5nMTAzMVxzYmFzZWRv
bjFcc25leHQzIEhlYWRpbmc7fQp7XHMzXHNhMTIwXGNmMHtcKlxoeXBoZW4yXGh5cGhsZWFk
MlxoeXBodHJhaWwyXGh5cGhtYXgwfVxydGxjaFxhZjNcYWZzMjRcbGFuZzI1NVxsdHJjaFxk
YmNoXGFmM1xsYW5nZmUyNTVcaGljaFxmMFxmczI0XGxhbmcxMDMxXGxvY2hcZjBcZnMyNFxs
YW5nMTAzMVxzYmFzZWRvbjFcc25leHQzIEJvZHkgVGV4dDt9CntcczRcc2ExMjBcY2Ywe1wq
XGh5cGhlbjJcaHlwaGxlYWQyXGh5cGh0cmFpbDJcaHlwaG1heDB9XHJ0bGNoXGFmM1xhZnMy
NFxsYW5nMjU1XGx0cmNoXGRiY2hcYWYzXGxhbmdmZTI1NVxoaWNoXGYwXGZzMjRcbGFuZzEw
MzFcbG9jaFxmMFxmczI0XGxhbmcxMDMxXHNiYXNlZG9uM1xzbmV4dDQgTGlzdDt9CntcczVc
c2IxMjBcc2ExMjBcY2Ywe1wqXGh5cGhlbjJcaHlwaGxlYWQyXGh5cGh0cmFpbDJcaHlwaG1h
eDB9XHJ0bGNoXGFmM1xhZnMyNFxsYW5nMjU1XGFpXGx0cmNoXGRiY2hcYWYzXGxhbmdmZTI1
NVxoaWNoXGYwXGZzMjRcbGFuZzEwMzFcaVxsb2NoXGYwXGZzMjRcbGFuZzEwMzFcaVxzYmFz
ZWRvbjFcc25leHQ1IGNhcHRpb247fQp7XHM2XGNmMHtcKlxoeXBoZW4yXGh5cGhsZWFkMlxo
eXBodHJhaWwyXGh5cGhtYXgwfVxydGxjaFxhZjNcYWZzMjRcbGFuZzI1NVxsdHJjaFxkYmNo
XGFmM1xsYW5nZmUyNTVcaGljaFxmMFxmczI0XGxhbmcxMDMxXGxvY2hcZjBcZnMyNFxsYW5n
MTAzMVxzYmFzZWRvbjFcc25leHQ2IEluZGV4O30KfQp7XGluZm97XGF1dGhvciBIYXJpbW9o
YW4gZGFzfXtcY3JlYXRpbVx5cjIwMDdcbW83XGR5MjVcaHIxMlxtaW4zMH17XHJldnRpbVx5
cjE2MDFcbW8xXGR5MVxocjBcbWluMH17XHByaW50aW1ceXIxNjAxXG1vMVxkeTFcaHIwXG1p
bjB9e1xjb21tZW50IFN0YXJXcml0ZXJ9e1x2ZXJuNjgwMH19XGRlZnRhYjcwOQp7XCpccGdk
c2N0YmwKe1xwZ2RzYzBccGdkc2N1c2UxOTVccGd3c3huMTE5MDVccGdoc3huMTY4MzdcbWFy
Z2xzeG4xMTM0XG1hcmdyc3huMTEzNFxtYXJndHN4bjExMzRcbWFyZ2JzeG4xMTM0XHBnZHNj
bnh0MCBTdGFuZGFyZDt9fQpccGFwZXJoMTY4MzdccGFwZXJ3MTE5MDVcbWFyZ2wxMTM0XG1h
cmdyMTEzNFxtYXJndDExMzRcbWFyZ2IxMTM0XHNlY3RkXHNia25vbmVccGd3c3huMTE5MDVc
cGdoc3huMTY4MzdcbWFyZ2xzeG4xMTM0XG1hcmdyc3huMTEzNFxtYXJndHN4bjExMzRcbWFy
Z2JzeG4xMTM0XGZ0bmJqXGZ0bnN0YXJ0MVxmdG5yc3Rjb250XGZ0bm5hclxhZW5kZG9jXGFm
dG5yc3Rjb250XGFmdG5zdGFydDFcYWZ0bm5ybGMKXHBhcmRccGxhaW4gXGx0cnBhclxzMVxj
ZjB7XCpcaHlwaGVuMlxoeXBobGVhZDJcaHlwaHRyYWlsMlxoeXBobWF4MH1ccnRsY2hcYWYz
XGFmczI0XGxhbmcyNTVcbHRyY2hcZGJjaFxhZjNcbGFuZ2ZlMjU1XGhpY2hcZjBcZnMyNFxs
YW5nMTAzMVxsb2NoXGYwXGZzMjRcbGFuZzEwMzEge1xydGxjaCBcbHRyY2hcbG9jaFxmMFxm
czI0XGxhbmcxMDMxXGkwXGIwIE51ciBlaW4gVGVzdC4uLn0KXHBhciB9");
  $file = "test.rtf";
  $handle = fopen($file, "w");
    if (fwrite($handle, base64_decode($data))) echo "Datei <samp>".$file."</samp> wurde angelegt.<br>";
    else echo "Datei <samp>".$file."</samp> konnte nicht angelegt werden. Prüfen Sie die Schreibrechte für das Verzeichnis <samp>".getcwd()."</samp>.<br>";
  fclose($handle);
  echo "<a href='".$file."'>Datei <samp>".$file."</samp> öffnen</a>";
?>

Mit der Funktion getcwd() (Zeile 44) kann das aktuelle Arbeitsverzeichnis ausgegeben werden.

Weitere Funktionen für das Handling von Dateien, die statt Text Datencode enthalten sind:

fseek() – Position des Datenzeigers setzen
ftell() – Position des Datenzeigers ausgeben
rewind() – Position des Datenzeigers an den Anfang setzen
fgetc() – Zeichen an der Position des Datenzeigers ausgeben
ftruncate() – Datei verkürzen (z. B. ftruncate($file, 0) leert die Datei $file ohne sie zu löschen)

Einzelheiten zu diesen Funktionen findet man im PHP Manual

Datei zeilenweise auslesen

Die Funktion fgets() liest eine Datei vom Anfang des Dateizeigers bis zum nächsten Zeilenumbruch (oder bis zum Ende der Datei) bzw. bis zur Länge eines optionalen zweiten Parameters (in Bytes; hier nicht angegeben) und setzt den Dateizeiger dann an das Ende der Abfrage. Die Funktion feof() überprüft, ob sich der Dateizeiger am Ende der Datei befindet. Auf diese Weise kann eine Schleife erzeugt werden, die die gesamte Datei zeilenweise ausliest.

Code kopieren
<?php
  $orte = array("Hamburg", "Berlin", "Hannover", "Köln", "Leipzig", "Dresden", "Frankfurt", "München", "Stuttgart");
  $file = "orte.txt";

  # Array in Datei schreiben
  $handle = fopen($file, "w");
    foreach ($orte as $value)
    if (!fwrite($handle, $value."\r\n")) echo "Datei <samp>".$file."</samp> konnte nicht angelegt werden. Prüfen Sie die Schreibrechte für das Verzeichnis <samp>".getcwd()."</samp>.<br>";
  fclose($handle);

  # Datei auslesen
  $handle = fopen($file, "r");
    while (!feof($handle)) echo fgets($handle)."<br>";
  fclose($handle);
?>

Mit der Funktion file() im nächsten Beispiel wird die Datei zeilenweise in ein Array geschrieben.

Um eine komplette Datei in einen String einzulesen, benötigt man lediglich die Funktion file_get_contents(). Um Daten in eine Datei zu schreiben kann man auch die Funktion file_put_contents() verwenden.

Um eine Datei direkt am Bildschirm auszugeben (z. B. HTML), wird die Funktion readfile() verwendet. Falls man eine auszuführende PHP-Datei einbinden möchte, muss man die Funktion include() verwenden, da mit readfile() der Code der PHP-Datei nicht ausgeführt, sondern eben nur angezeigt wird.

Code kopieren
<?php
  $orte = array("Hamburg", "Berlin", "Hannover", "Köln", "Leipzig", "Dresden", "Frankfurt", "München", "Stuttgart");
  $file = "orte.txt";

  # Array in Datei schreiben
  $handle = fopen($file, "w");
    foreach($orte as $value)
    if (!fwrite($handle, $value."\r\n")) echo "Datei <samp>".$file."</samp> konnte nicht angelegt werden. Prüfen Sie die Schreibrechte für das Verzeichnis <samp>".getcwd()."</samp>.<br>";
  fclose($handle);
  
  # Datei in Array schreiben
  $orte = file($file);
  
  # Array ausgeben
  foreach ($orte as $value) echo $value."<br>";

  # Datei komplett auslesen
  echo "<br>".file_get_contents($file)."<br><br>";
  
  # Datei direkt anzeigen
  readfile($file);

  # Daten in Datei schreiben
  echo "<br>".file_put_contents($file, "Hallo Welt!")."<br><br>";
?>

Datei ändern

Wenn man in einer Textdatei eine (oder mehrere) Zeilen ändern möchte, kann man den Inhalt der Datei mit file() zeilenweise in ein Array schreiben (Zeile 12), die gewünschten Werte ändern und das aktualisierte Array wieder in die Datei zurückschreiben.

Code kopieren
<?php
  $orte = array("Hamburg", "Berlin", "Hannover", "Köln", "Leipzig", "Dresden", "Frankfurt", "München", "Stuttgart");
  $file = "orte.txt";
  
  # Array in Datei schreiben
  $handle = fopen($file, "w");
    foreach ($orte as $value)
    if (!fwrite($handle, $value."\r\n")) echo "Datei <samp>".$file."</samp> konnte nicht angelegt werden. Prüfen Sie die Schreibrechte für das Verzeichnis <samp>".getcwd()."</samp>.<br>";
  fclose($handle);
  
  # Datei in Array schreiben und Zeilenumbrüche tilgen
  $temp = array_map('rtrim', file($file));
  
  # Werte ersetzen
  $temp[array_search("Köln", $temp)] = "Düsseldorf";
  $temp[array_search("Stuttgart", $temp)] = "Freiburg";
  
  # Datei aktualisieren
  $handle = fopen($file, "w");
    foreach ($temp as $value)
    if (!fwrite($handle, $value."\r\n")) echo "Datei <samp>".$file."</samp> konnte nicht angelegt werden. Prüfen Sie die Schreibrechte für das Verzeichnis <samp>".getcwd()."</samp>.<br>";
  fclose($handle);
  
  # Datei auslesen
  $handle = fopen($file, "r");
    while (!feof($handle)) echo fgets($handle)."<br>";
  fclose($handle);
?>

Zeichenseparierte Werteliste (CSV)

Will man eine Textdatei auslesen, die eine zeichenseparierte Werteliste enthält, wird dazu die Funktion fgetcsv() verwendet (Zeile 22). Im zweiten Parameter muss ein Wert angegeben werden, der mindestens so groß ist wie die Länge der längsten Zeile der Datei. Der dritte Parameter gibt das Trennzeichen ($separator) an. Dieses Zeichen darf natürlich in keinem der Werte selbst vorhanden sein.

Das Ergebnis der Funktion fgetcsv() wird in ein Array geschrieben, das man anschließen auslesen kann.

Code kopieren
<style>
  td { border:1px solid #ccc; }
</style>
<?php
  $orte = array("Hamburg", "Berlin", "Hannover", "Köln", "Leipzig", "Dresden", "Frankfurt", "München", "Stuttgart");
  $flaeche = array("755", "890", "204", "405", "297", "328", "248", "310", "207");
  $einwohner = array("1740000", "3400000", "515000", "980000", "503000", "495000", "652000", "1260000", "593000");
  $file = "orte.txt";
  $separator = "|";

  # Arrays in Datei schreiben
  $handle = fopen($file, "w");
  for ($n = 0; $n < count($orte); $n++) {
    $value = $orte[$n].$separator.$flaeche[$n].$separator.$einwohner[$n];
    if (!fwrite($handle, $value."\r\n")) echo "Datei <samp>".$file."</samp> konnte nicht angelegt werden. Prüfen Sie die Schreibrechte für das Verzeichnis <samp>".getcwd()."</samp>.<br>";
  }
  fclose($handle);

  # Datei auslesen
  $handle = fopen($file, "r");
  $count = 0;
  while ($data = fgetcsv($handle, 1000, $separator)) {
    foreach ($data as $value) $stats[$count][] = $value;
    $count++;
  }
  fclose($handle);
  
  # Array ausgeben
  echo "<table><tr><th>Ort</th><th>Fläche</th><th>Einwohner</th></tr>";
  foreach ($stats as $value)
    echo "<tr><td>".$value[0]."</td><td style='text-align:right;'>".$value[1]." km²</td><td style='text-align:right;'>".number_format($value[2], 0, ",", " ")."</td></tr>";
  echo "</table>";
?>

Verzeichnisinhalt und Dateieigenschaften

Das folgende Skript veranschaulicht einige weitere Funktionen, mit denen man den Inhalt eines Verzeichnisses auslesen und diverse Eigenschaften der enthaltenen Dateien ausgeben kann.

is_dir() – prüft, ob ein Verzeichnis existiert
opendir() – öffnet ein Verzeichnis
readdir() – liest ein Verzeichnis aus
closedir() – schließt ein Verzeichnis

filetype() – Typ (Datei oder Verzeichnis)
mime_content_type() – MIME-Typ einer Datei
filectime() – Zeitstempel der Änderung der Metadaten einer Datei
filemtime() – Zeitstempel der Änderung des Inhalts einer Datei
fileatime() – Zeitstempel des letzten Zugriffs auf eine Datei

Code kopieren
<style>
  td { border:1px solid #ccc; }
</style>
<?php
  $dir = "/pfad/zum/verzeichnis/";
  if (is_dir($dir)) {
    if ($handle = opendir($dir)) {
      echo "<table><thead><tr><th>Datei</th>";
      echo "<th>Typ</th>";
      echo "<th>MIME-Typ</th>";
      echo "<th>Größe</th>";
      echo "<th>Änderung Metadaten</th>";
      echo "<th>Änderung Inhalt</th>";
      echo "<th>Letzter Zugriff</th></tr></thead>";
      while ($file = readdir($handle)) {
        echo "<tr><td>".$file."</td>";
        echo "<td>".filetype($dir.$file)."</td>";
        echo "<td>".mime_content_type($dir.$file)."</td>";
        echo "<td style='text-align:right;'>".filesize($dir.$file)." Bytes</td>";
        echo "<td>".date("r", filectime($dir.$file))."</td>";
        echo "<td>".date("r", filemtime($dir.$file))."</td>";
        echo "<td>".date("r", fileatime($dir.$file))."</td></tr>";
      }
      echo "</table>";
    } else echo "Für das Verzeichnis <samp>".$dir."</samp> bestehen keine Leserechte!";
    closedir($handle);
  } else echo "Das Verzeichnis <samp>".$dir."</samp> existiert nicht!";
?>

Das Öffnen und Schließen des Verzeichnisses ist nur für die Funktion readdir() notwendig, die sämtliche Dateien eines Verzeichnisses auflistet. Die Ausgabe der Eigenschaften einer einzelnen Dateien kann auch ohne readdir() erfolgen.

All diese Eigenschaften (und noch mehr) können auch mit der Funktion stat() ermittelt werden, die diese Werte allerdings in ein Array schreibt.

Da die Dateien im obigen Beispiel in der Reihenfolge ihrer Speicherung im Dateisystem angezeigt werden – also nicht unbedingt alphabetisch – muss die Ausgabe der Dateien über ein sortiertes Array erfolgen, wenn man eine alphabetische Sortierung benötigt:

Code kopieren
<style>
  td { border:1px solid #ccc; }
</style>
<?php
  $dir = "/pfad/zum/verzeichnis/";
  if (is_dir($dir)) {
    if ($handle = opendir($dir)) {
      while ($file = readdir($handle)) {
        $files[0][] = $file;
        $files[1][] = filetype($dir.$file);
        $files[2][] = mime_content_type($dir.$file);
        $files[3][] = filesize($dir.$file);
        $files[4][] = filectime($dir.$file);
        $files[5][] = filemtime($dir.$file);
        $files[6][] = fileatime($dir.$file);
      }
    } else echo "Für das Verzeichnis <samp>".$dir."</samp> bestehen keine Leserechte!";
    closedir($handle);
  } else echo "Das Verzeichnis <samp>".$dir."</samp> existiert nicht!";
  $files_lc = array_map('strtolower', $files[0]);
  array_multisort($files[1], $files_lc, $files[0], $files[2], $files[3], $files[4], $files[5], $files[6]);
  echo "<table><thead><tr><th>Datei</th>";
  echo "<th>Typ</th>";
  echo "<th>MIME-Typ</th>";
  echo "<th>Größe</th>";
  echo "<th>Änderung Metadaten</th>";
  echo "<th>Änderung Inhalt</th>";
  echo "<th>Letzter Zugriff</th></tr></thead>";
  for ($row = 0; $row < count($files[0]); $row++) {
    echo "<tr><td>".$files[0][$row]."</td>";
    echo "<td>".$files[1][$row]."</td>";
    echo "<td>".$files[2][$row]."</td>";
    echo "<td style='text-align:right;'>".$files[3][$row]." Bytes</td>";
    echo "<td>".date("r", $files[4][$row])."</td>";
    echo "<td>".date("r", $files[5][$row])."</td>";
    echo "<td>".date("r", $files[6][$row])."</td></tr>";
  }
  echo "</table>";
?>

In Zeile 915 werden die Eigenschaften in das Array $files geschrieben. Dies wird nun in Zeile 21 sortiert, wobei das erste Sortierkriterium der Typ (Datei bzw. Verzeichnis) ist. Das zweite Kriterium ist ein Kopie des Arrays mit den Dateinamen in Kleinschreibung (Zeile 20), damit die Sortierung nicht case-sensitive erfolgt.

Verzeichnisbaum

Folgendes Skript veranschaulicht, wie mit Hilfe der Funktion scandir() ein Verzeichnisbaum erstellt werden kann:

Code kopieren
<?php
  header("Content-Type: text/html; charset=utf-8");
  function html($str) {
    return htmlspecialchars($str, ENT_NOQUOTES, 'UTF-8');
  }
  function dirtree($dir, $indent) {
    $tree = "";
    if (is_readable($dir)) {
      $subtree = "";
      $dirscan = scandir($dir);
      foreach ($dirscan as $object) {
        if ($object != "." && $object != ".." && is_dir($dir.$object)) {
          $subtree .= $indent."    <li>".html($object);
          $subtree .= dirtree($dir.$object."/", $indent."    ");
          $subtree .= "</li>\r\n";
        }
      }
      if ($subtree != "") {
        $tree .= "\r\n".$indent."  <ul>\r\n";
        $tree .= $subtree;
        $tree .= $indent."  </ul>\r\n".$indent;
      }
      reset($dirscan);
    }
    return $tree;
  }
  echo "<!DOCTYPE HTML>
<html lang='de'>
  <head>
    <title>Dateisystem</title>
    <meta charset='UTF-8'>
    <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
  </head>
  <body>";
  echo dirtree($_SERVER['DOCUMENT_ROOT']."/", "  ");
  echo "</body>
</html>";
?>

Datei kopieren, umbenennen und löschen

Im folgenden Skript werden diese Funktionen angewendet:

copy() – eine Kopie einer Datei anlegen
rename() – eine Datei umbenennen
unlink() – eine Datei löschen

Code kopieren
<?php
  $file_old = "test.txt";
  $file_new = "test_copy.txt";
  $file_brandnew = "test_brandnew.txt";
  if (!copy($file_old, $file_new)) echo "Die Datei <samp>".$file_old."</samp> konnte nicht kopiert werden!";
  if (!rename($file_new, $file_brandnew)) echo "Die Datei <samp>".$file_new."</samp> konnte nicht umbenannt werden!";
  if (!unlink($file_old)) echo "Die Datei <samp>".$file_old."</samp> konnte nicht gelöscht werden!";
?>

Man kann als Parameter auch einen Pfad angeben. Wird bei rename() als zweiter Parameter ein anderes Verzeichnis als das im ersten Parameter angegeben, wird die Datei dorthin verschoben, sofern dort Schreibrechte bestehen.

Existieren bei copy() und rename() die Dateien des zweiten Parameters bereits, werden diese ohne Warnung überschrieben.

Ordner löschen

Um einen Ordner zu löschen, verwendet man die Funktion rmdir($dir). Allerdings funktioniert diese Funktion nur, wenn der betreffende Ordner im Pfad $dir auch leer ist. Ansonsten kann man folgende Funktion verwenden, um Ordner einschließlich sämtlicher Inhalte zu löschen, vorausgesetzt, man verfügt über die notwendigen Rechte:

Code kopieren
function rrmdir($dir) {
  if (is_dir($dir)) {
    $dirscan = scandir($dir);
    foreach ($dirscan as $object) {
      if ($object != "." && $object != "..") {
        if (is_link($dir."/".$object)) {  # object is symlink
          if (!unlink($dir."/".$object)) return FALSE;
        } elseif (is_dir($dir."/".$object)) {  # object is folder
          if (!rrmdir($dir."/".$object)) return FALSE;
        } else {  # object is file
          if (!unlink($dir."/".$object)) return FALSE;
        }
      }
    }
    reset($dirscan);
    if (!rmdir($dir)) return FALSE;
    return TRUE;
  } else return FALSE;
}