Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Geleitwort
Vorwort
1 PEAR – Einführung
2 Authentication
3 Caching
4 Date and Time
5 File Formats
6 HTTP
7 Internationalization
8 Mail
9 Networking
10 PHP
11 Text
12 Web Services
13 Benchmarking
14 Configuration
15 Database
16 File System
17 HTML
18 Images
19 Logging
20 Math
21 Numbers
22 Tools and Utilities
23 XML
24 Selbst Pakete erstellen
25 PECL
Index
Ihre Meinung?

Spacer
 <<   zurück
PHP PEAR von Carsten Möhrke
Anwendung und Entwicklung – Erweiterungen für PHP schreiben
Buch: PHP PEAR

PHP PEAR
798 S., 39,90 Euro
Rheinwerk Computing
ISBN 3-89842-580-0
gp 16 File System
  gp 16.1 File
  gp 16.2 File_Find
  gp 16.3 File_SearchReplace

16 File System

Die Kategorie »File     System« umfasst einige Pakete, die den Umgang mit dem Dateisystem und Dateien erleichtern sollen. Es handelt sich hierbei allerdings nicht um Funktionalitäten, die vom Typ der Datei abhängen, sondern um allgemeine Tools.


Rheinwerk Computing

16.1 File  toptop


Besprochene Version: 1.1.0RC5 Lizenz: PHP-Lizenz 3.0
Klassendatei(en): File.php; File/CSV.php; File/Util.php

Das Paket File ist eine Art Schweizer Messer für den Umgang mit Dateien und Verzeichnissen. Die drei Dateien, die im Paket enthalten sind, dienen alle einem speziellen Zweck. File.php ist darauf ausgelegt, direkt mit Dateien zu arbeiten, sie also zu lesen, zu schreiben und Ähnliches. CSV.php ist, wie der Name schon vermuten lässt, auf CSV-Dateien spezialisiert. Util.php enthält einige hilfreiche Funktionalitäten für den allgemeinen Umgang mit Dateien und Verzeichnissen.

Die Funktionalitäten der Klasse File beschränken sich primär darauf, Daten aus Dateien zu lesen bzw. diese wieder zu schreiben. Auch wenn die PHP-Funktionen das natürlich auch leisten, so bieten die hier enthaltenen Methoden doch einige Vereinfachungen.

Möchten Sie eine Datei zeilenweise einlesen, steht readLine() zur Verfügung. Diese Methode bekommt den Namen einer Datei übergeben und liest die jeweils nächste Zeile aus – beim ersten Aufruf die erste Zeile, beim zweiten Aufruf die zweite und so weiter, bis das Dateiende erreicht ist. Ist das der Fall, gibt die Methode false zurück. Interessant ist hierbei, dass die Methode – wie die anderen auch – statisch genutzt werden kann, ohne dass Sie einen File-Pointer nutzen müssen.

require_once('File.php'); 
// Name der Datei 
$file='daten.txt'; 
// Einlesen, bis die Methode false liefert 
while (false!==($dat=File::readLine($file,true))) 
{ 
   // Fehler aufgetreten? 
   if (true===PEAR::isError($dat)) 
   { 
      echo 'Ein Fehler ist aufgetreten:<br />'; 
      die ($dat->getMessage()); 
   } 
   // Eingelesene Zeile ausgeben 
   echo $dat; 
}

Listing 16.1 Zeilenweises Verarbeiten einer Datei

In Listing 16.1 finden Sie ein Script, das eine Datei Zeile für Zeile einliest und direkt ausgibt. Die Methode readLine() bekommt als ersten Parameter den Namen der Datei übergeben. Das true, das danach folgt, ist optional und definiert, dass die zu lesende Datei mit einem Lock versehen werden soll, so dass kein zweiter, paralleler Zugriff möglich ist. Standardmäßig werden die Dateien nicht mit einem Lock belegt.

Die Methode öffnet die Datei automatisch und liefert die eingelesene Zeile zurück. Trifft sie auf das Dateiende, gibt sie false zurück. Hierdurch erklärt sich auch die auf den ersten Blick etwas komplexe Bedingung in der while-Schleife:

while(false!==($dat=File::readLine($file,true)))

Die Schleife darf nämlich erst dann enden, wenn das Ergebnis der Methode false ist. Wichtig ist hierbei der !== Operator. Bei einem einfachen Ungleich würde die Schleife auch bei einer Leerzeile abbrechen. Tritt ein Fehler auf, ist der Rückgabewert ein PEAR_Error-Objekt.

Weitere Methoden zum Einlesen von Daten sind readAll(), readChar() und read(). Die ersten beiden Methoden haben eine mit readLine() identische Parameterliste. readAll() liefert Ihnen den kompletten Inhalt der Datei auf einmal, und readChar() gibt immer ein einzelnes Zeichen zurück. read() ist die flexibelste Methode zum Auslesen von Daten. Sie bekommt den Dateinamen übergeben und akzeptiert als zweiten Parameter noch die Anzahl der Zeichen, die bei jedem Lesevorgang erfasst werden sollen. Übergeben Sie diesen zweiten Wert nicht, werden bei jedem Lesevorgang standardmäßig 1024 Zeichen ausgelesen. Auch hier ist es möglich, einen weiteren booleschen Wert anzufügen, der festlegt, ob ein Lock auf die Datei gelegt werden soll.

Natürlich existieren auch Member-Funktionen zum Schreiben von Daten, die sehr ähnlich aufgebaut sind. writeLine() schreibt beispielsweise jeweils eine Zeile in die Datei, deren Name als erster Parameter übergeben wird. Der zweite obligatorische Parameter ist der Text, der in die Datei eingefügt werden soll. Zusätzlich können Sie den Schreibmodus, die Definition des Zeilenumbruchs sowie einen booleschen Wert angeben, um das Locking einzuschalten. Für die Angabe des Schreibmodus sind die Konstanten FILE_MODE_APPEND (Anhängen, Default-Wert) und FILE_MODE_WRITE (Überschreiben) definiert. Der Zeilenumbruch kann frei definiert werden. Der Standard ist, dass ein '\n' (Unix-Zeilenumbruch) genutzt wird, aber Sie können natürlich auch die DOS- ('\r\n')- oder die Mac OS 9- ('\r')-Variante nutzen.

Die beiden anderen Schreibmethoden sind write() und writeChar(). Die erste schreibt frei definierbare Daten in eine Datei, und die zweite schreibt jeweils ein Zeichen. Bei beiden Methoden erfordert der Aufruf den Dateinamen und den zu speichernden Inhalt als Parameter. Optional können auch hier der Schreibmodus sowie das Locking-Verhalten festgelegt werden.

Auch die Schreibmethoden geben im Fall eines Fehlers jeweils einen PEAR_Error zurück.

Natürlich ist auch eine Methode namens rewind() definiert, mit der Sie den Dateizeiger der Datei, deren Namen Sie übergeben, wieder auf den Anfang setzen können.

Zwar schließt PHP bei Ende des Scripts alle offenen Dateien, aber es kann im Einzelfall auch mal nötig oder geschickt sein, die Dateien manuell zu schließen. Möchten Sie alle Dateien schließen, übernimmt closeAll() die Aufgabe. Eine einzelne Datei kann mit der Methode close() geschlossen werden. Sie bekommt den Dateinamen und den Modus übergeben, in dem die Datei geöffnet wurde. Auch unlock(), eine Methode, mit der Sie ein Datei-Lock aufheben können, bekommt dieselben Parameter übergeben.

Zur Übernahme tabellarisch darstellbarer Daten werden gerne CSV-Dateien genutzt. CSV steht für Comma Separated Values und bedeutet, dass die einzelnen Datenspalten mithilfe bestimmter, festgelegter Zeichen gegeneinander abgegrenzt werden. Eine solche Datei könnte beispielsweise so aufgebaut sein:

Artikel;Anzahl;Preis 
Jacke;10;89,00 
"Schuhe";5;139,00 
Hose;21;39,90

In diesem Fall sind die drei Spalten also jeweils mit einem Semikolon voneinander getrennt. Dabei sind allerdings auch andere Trennzeichen wie Doppelpunkt oder Komma möglich. Um einen möglichst unproblematischen Umgang mit solchen Dateien zu ermöglichen, stellt die Klasse File_CSV beispielsweise die Methode discoverFormat() bereit, die selbstständig herauszufinden versucht, wie eine CSV-Datei aufgebaut ist. Das Einlesen und Auswerten einer CSV-Datei mit File_CSV könnte so funktionieren, wie in Listing 16.2 dargestellt.

require_once('File/CSV.php'); 
$file='daten.txt'; 
$conf=File_CSV::discoverFormat($file); 
if (PEAR::isError($conf)) 
{ 
   die ($conf->getMessage()); 
} 
echo '<table border="1">'; 
echo "<tr><td colspan='$conf[fields]'> 
         Preisliste</td></tr>"; 
while (@$daten=File_CSV::read($file,$conf)) 
{ 
   if ((true === is_array($daten)) && 
       ($conf['fields'] === count($daten))) 
   { 
      echo "<tr><td>"; 
      echo implode('</td><td>',$daten); 
      echo "</td></tr>"; 
   } 
} 
echo '</table>';

Listing 16.2 Verarbeitung einer CSV-Datei

Die Methode discoverFormat() liefert ein Array zurück, in dem die relevanten Informationen angelegt sind und das für die anderen Methoden weiterverwendet werden kann. Der Schlüssel fields enthält hierbei die Anzahl der Spalten, die ermittelt wurden. sep verweist auf das Trennzeichen, und im Feld quote übergibt die Methode Anführungszeichen, die teilweise genutzt werden, um die Werte der Felder einzuschließen. Wurden keine Anführungszeichen in den ersten fünf Zeilen der Datei gefunden, ist der Inhalt des Feldes null.

discoverFormat() erkennt standardmäßig einen Tabulatorsprung (\t), ein Semikolon, ein Komma oder einen Doppelpunkt als Trennzeichen. Soll die Methode noch andere Zeichen erkennen, wie z. B. das Pipe-Symbol (|), so können Sie diese Zeichen in Form eines Arrays als zweiten Parameter übergeben.

Zum eigentlichen Einlesen der Datei wird read() genutzt. Die Methode bekommt wiederum den Dateinamen und das von discoverFormat() zurück-gelieferte Array übergeben. Der Rückgabewert ist ein Array, in dem die einzelnen Datenfelder enthalten sind. Standardmäßig werden die Anführungszeichen – wenn discoverFormat() sie erkannt hat – entfernt. Möchten Sie das verhindern, hilft Ihnen ein unset($conf['quote']) weiter.

Ein wenig ungewöhnlich für PEAR ist der Fehlerunterdrückungsoperator (@) in der while-Schleife. Leider wird dieser benötigt, weil eine der genutzten Funktionen zurzeit noch eine Warnung ausgibt, wenn in einer Zeile nur ein Datenfeld enthalten ist. Daher wird in der Schleife vor der Ausgabe auch mit is_array() geprüft, ob ein Array oder besagte Warnung in der Variable enthalten ist. Sollten in einer Zeile weniger Felder enthalten sein als erwartet, so wird diese übersprungen, was durch den zweiten Teil der Bedingung gewährleistet wird. In zukünftigen Versionen soll die Fehlerbehandlung hier über einen PEAR_Error-Objekt gehandhabt werden. Die Browserausgabe von Listing 16.2 finden Sie in Abbildung 16.1.

Abbildung 16.1 Ausgabe der CSV-Daten im Browser

Die Methode write() dient dazu, Daten in eine CSV-Datei zu schreiben. Der erste Parameter ist hierbei der Dateiname und der zweite ein Array mit den Daten, die in die Datei geschrieben werden sollen. Als dritter Parameter wird ein Array mit den Feldern übergeben, wie es bei discoverFormat() beschrieben ist. Die Anzahl der Felder, die darin definiert ist, muss mit der Anzahl der Felder in dem Array übereinstimmen, da die Methode sonst ein PEAR_Error-Objekt liefert. Alle Datenfelder werden in die Art von Anführungszeichen verpackt, die im Feld quote übergeben wurden. Sollen die Daten nicht »gequotet« werden, übergeben Sie einfach einen Leerstring oder null in dem Element.

Dieses Array muss aber zusätzlich noch den Schlüssel crlf enthalten, der definiert, mit welcher Zeichenkombination (z. B. \n oder \r\n) eine Zeile beendet werden soll.

Die letzte Klasse dieses Pakets ist File_Util. In ihr sind einige hilfreiche Funktionen zum Umgang mit Verzeichnissen und Pfaden definiert. Wichtig ist, dass die Methoden jeweils nur mit Pfaden umgehen können, die in der Syntax des Betriebssystems formuliert sind, auf dem die Anwendung ausgeführt wird.

So können Sie mithilfe der Methode isAbsolute() prüfen, ob es sich bei dem übergebenen String um eine absolute Pfadangabe handelt. Hierbei wird allerdings nur der Aufbau des übergebenen Strings geprüft und nicht, ob der Pfad existiert.

Nutzen Sie einen absoluten Pfad, kann es gerade unter Windows hilfreich sein, den Bezug zur Wurzel bzw. zum Laufwerk zu entfernen. Genau das ist es, was die Methode skipRoot() leistet, wenn ihr ein absoluter Pfad übergeben wird. Ein relativer Pfad wird unverändert zurückgegeben.

require_once('File/Util.php'); 
 
$unix_pfad='/var/www/htdocs'; 
echo (File_Util::skipRoot($unix_pfad)); 
// Gibt auf Unix-Systemen var/www/htdocs aus 
 
$win_pfad='C:\xampp\htdocs'; 
echo (File_Util::skipRoot($win_pfad)); 
// Gibt auf Windows-Systemen xampp\htdocs aus

Die Methode realPath() bekommt einen relativen Pfad übergeben und ergänzt ihn so, dass sich daraus ein absoluter Pfad ergibt. Auch sie überprüft nicht, ob es den Pfad gibt oder nicht.

require_once('File/Util.php'); 
$pfad='daten'; 
echo (File_Util::realPath($pfad)); 
// Gibt z. B. /home/net/public_html/daten aus

In eine etwas andere Richtung geht die Methode relativePath(), die zwei Verzeichnisse übergeben bekommt. Die Methode bestimmt die relative Pfadangabe, um das erste Verzeichnis ausgehend von dem zweiten zu adressieren.

$pfad='/home/geheim'; 
$root='/home/net/public_html'; 
echo (File_Util::relativePath($pfad, $root)); 
// Gibt ../../geheim aus

Beide Pfade, die Sie hier nutzen, sollten absolute Pfade sein, damit die Methode einen eindeutigen Bezugspunkt für beide Verzeichnisse hat.

Auch pathInRoot() bekommt zwei Pfadangaben mit auf den Weg. Sie prüft, ob der erste übergebene Pfad Teil des zweiten ist. Das heißt, wenn Sie die Pfade /home und /home/net/public_html übergeben, bestätigt die Methode mit einem true, dass der erste Pfad im zweiten liegt. Ist der erste Pfad relativ, so wird er ausgehend von dem aktuellen Arbeitsverzeichnis um einen Bezug zum Root-Verzeichnis ergänzt.

Eine weitere spannende Methode ist listDir(). Sie bekommt mindestens einen Pfad als Parameter übergeben, liest das damit verbundene Verzeichnis aus und gibt die darin enthaltenen Daten in Form eines Arrays zurück. Hierbei handelt es sich um ein indiziertes Array, das für jeden Eintrag im Directory ein Objekt der Klasse stdClass [Hierbei handelt es sich um eine Klasse, die PHP nutzt, wenn beliebige Daten in ein Objekt konvertiert werden. ] enthält. Folgendes Beispiel liest einen beliebigen Datensatz (in diesem Fall den 42.) aus:

require_once('File/Util.php'); 
$daten=(File_Util::listDir('.')); 
$eine_zeile=$daten[41]; 
echo "Name: $eine_zeile->name<br />"; 
echo "Size (in Byte): $eine_zeile->size<br />"; 
echo "Timestamp: $eine_zeile->date<br />";

Dann generiert es diese Ausgabe:

Name: hl.php 
Size (in Byte): 549 
Timestamp: 1103886568

Mehr Informationen zu einem Datensatz werden nicht erfasst, aber ich denke, dass man mit diesen Daten schon einiges anfangen kann. Handelt es sich nicht um eine Datei, sondern um ein Unterverzeichnis, das gefunden wird, bekommt der Schlüssel Size den Wert null zugewiesen.

Mit einem zweiten Parameter können Sie zusätzlich noch definieren, welche Inhalte eines Verzeichnisses zurückgeliefert werden. Die Konstante FILE_LIST_ALL, die auch dem Standardwert entspricht, sorgt dafür, dass die Methode alle Einträge zurückgibt. Mit FILE_LIST_DIRS werden nur Verzeichnislinks und mit FILE_LIST_FILES nur Dateieinträge zurückgegeben.

Zusätzlich ist es möglich, mit einem dritten Wert die Sortierreihenfolge zu definieren. Normalerweise werden die Einträge unsortiert zurückgegeben, was der Konstante FILE_SORT_NONE entsprechen würde. FILE_SORT_NAME liefert die Dateien aufsteigend nach Namen sortiert, und FILE_SORT_REVERSE dreht diese Sortierreihenfolge um. Zusätzlich können Sie noch nach Datum bzw. Uhrzeit (FILE_SORT_DATE) oder Größe (FILE_SORT_SIZE) ordnen lassen. Eine Kombination dieser Werte ist zurzeit nicht vorgesehen.

Wie im richtigen Leben kommt aber auch hier das Beste zuletzt. Mit dem letzten Parameter können Sie eine Callback-Funktion definieren. Dabei handelt es sich um eine Funktion, die für jeden gefundenen Datensatz aufgerufen wird und jeweils den Namen des gefundenen Eintrags übergeben bekommt. Somit steht eine schnelle und einfache Möglichkeit zur Verfügung, mit jedem Eintrag eine Aktion auszuführen.

require_once('File/Util.php'); 
// Funktion zum Kopieren der Daten 
function backup ($name) 
{ 
   // Liegt eine PHP-Datei vor? 
   if (true == preg_match('/.*php$/i',$name)) 
   { 
      // Kopieren und true zurueckgeben 
      copy("./$name","./backups/$name"); 
      return true; 
   } 
   // Wenn es keine PHP-Datei war, false zurueckgeben 
   return false; 
} 
 
$daten=(File_Util::listDir('.', //Aktuelles Verzeichnis nutzen 
                      FILE_LIST_FILES, // Nur Dateien 
                      FILE_SORT_NONE, // Nicht sortieren 
                      'backup' // Name der Callback-Funktion 
                 )); 
echo 'Es wurden '.count($daten).' Dateien kopiert';

Listing 16.3 Kopieren aller PHP-Dateien aus einem Verzeichnis

In Listing 16.3 finden Sie ein Script, das mithilfe einer Callback-Funktion alle Dateien mit der Endung .php kopiert. Interessant ist, dass die Methode listDir() nur diejenigen Werte zurückgibt, bei denen die Callback-Funktion mit true bestätigt hat, dass das passieren soll. Somit finden sich in $daten nur Einträge, die auch wirklich auf .php enden. Somit kann eine Callback-Funktion auch durchaus für weitergehende Filter-Möglichkeiten genutzt werden.

Um die Arbeit mit temporären Dateien zu vereinfachen, sind die beiden Methoden tmpDir() und tmpFile() vorgesehen. Die erste liefert hierbei den Pfad des temporären Verzeichnisses zurück, das auf dem System genutzt wird. Die zweite Methode liefert Ihnen einen eindeutigen Dateinamen für eine temporäre Datei zurück. Übergeben Sie ihr kein Verzeichnis, nutzt sie das vordefinierte temporäre Verzeichnis des Servers. Allerdings können Sie auch einen anderen Pfad übergeben, der dann als Grundlage genutzt wird. In beiden Fällen wird der Dateiname inklusive des Pfads zurückgegeben, so dass dieser direkt mit fopen() verwendet werden kann.

 <<   zurück
     
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: PHP PEAR
PHP PEAR
Jetzt Buch bestellen!
 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchtipps
Zum Rheinwerk-Shop: PHP 5.6 und MySQL 5.7






 PHP 5.6 und
 MySQL 5.7


Zum Rheinwerk-Shop: Einstieg in PHP 5.6 und MySQL 5.6






 Einstieg in PHP 5.6
 und MySQL 5.6


Zum Rheinwerk-Shop: Responsive Webdesign






 Responsive Webdesign


Zum Rheinwerk-Shop: Moderne Websites entwickeln






 Moderne Websites
 entwickeln


Zum Rheinwerk-Shop: MySQL 5.6






 MySQL 5.6


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo








Copyright © Rheinwerk Verlag GmbH 2007
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern