Skip to content

Arbeiten mit CSV Dateien

Mit CSV Dateien lässt sich dank der einheitlichen Struktur deutlich besser arbeiten,
als mit normalen Textdateien. In den meisten Programmiersprachen sind bereits Funktionen und Klassen enthalten,
die das Arbeiten mit CSV Dateien erleichtern und die neu Entwicklung einer eigenen Klasse für das Handling entfällt.

Der klare Vorteil liegt in der meist gleichen Struktur. Ein Zeichen dient als delimiter und begrenzt so zu sagen die Spalte (meist , oder ; ).
Ein anderes Zeichen dient als enclosure und ermöglicht auch delimiter zu nutzen ohne das die gesamte Struktur zerstört wird ( meist " oder ' ).
Natürlich wird immer ein sogenanntes escape-Zeichen benötigt um die reservierten Zeichen dennoch darstellen zu können.

Ein Beispiel:
Tastatur,Maus,Monitor
Array ( [0] => Tastatur, [1] => Maus, [2] => Monitor )

"Tastatur,Maus",Monitor
Array ( [0] => Tastatur,Maus, [1] => Monitor )


Wie oben sichtbar wird, wird alles zwischen " in eine Spalte des Arrays gepackt und das Trennzeichen hier ignoriert,
nun muss eventuell " genutzt werden dies wird in PHP, wie bei den meisten anderen Funktionen mittels \" escaped.

Leider besteht hier ein kleiner Haken, das \" wird im Array natürlich genau so dargestellt,
d.h. es muss mittels Suchen und Ersetzen ausgetauscht werden.

Das Schreiben der Daten erfolgt wie bei einer Textdatei mittels fwrite.

Funktion
fgetcsv ( $handle, $length, $delimiter, $enclosure, $escape )


$handle (Pflichtwert!)
ein offener Dateizeiger mittels fopen.

$length (Standardwert: 0)
Länge der längsten Zeile, ist seit PHP 5.0 optional, seit PHP 5.0.4 bei Wert 0 ist die Zeilenlänge unbegrenzt, dadurch aber etwas langsamer.

$delimiter (Standardwert: , (Komma))
Nur ein Zeichen erlaubt, alles andere wird ignoriert. Dient als Trennzeichen zwischen den Spalten.

$enclosure (Standardwert: " (Anführungszeichen)
Nur ein Zeichen erlaubt, alles andere wird ignoriert. Dient als Texttrenner, damit die Zeichen von $delimiter im eingeschlossenen Text genutzt werden können

$escape (Standardwert: \\)
Dient dazu $enclosure Zeichen zu escapen, damit diese darin genutzt werden können.


Snippet

$fp = fopen ( 'test.csv', 'r' );
while ( $data = fgetcsv ( $fp , 0 , ',' , '"' ) )
{
        print_r($data);
}
fclose ( $fp );

Arbeiten mit ASCII Dateien

Also ASCII-Dateien sind reine Textdateien, dabei ist die Endung völlig egal, der Vorteil von diesen Arten ist, überall wo php möglich ist, geht diese Art, damit kann man auch ein Forum betreiben oder sogar Chats!
Nachteil: Ab 8 MB wird es kritisch, arbeiten mit ASCII-Datenbanken oder Flatfiles ist immer etwas kritisch, da diese direkt eingesehen werden können und gegenüber Datenbank-Systemen wie mySQL, MSSQL oder PostgreSQL ziemlich langsam sind.
Seit PHP 5 gibt es eine sogenannte SQLite Version, dies ist nichts anderes als eine Art Datenbank, aber es wird eine einfache Textdatei verwendet, diese Datei ist natürlich unbrauchbar ohne PHP 5 oder ähnlicher Programmiersprache oder Software, die die Daten lesen kann.

Auf vorhandene Datei prüfen
if(file_exists("Datei.txt"))
{
        //Hier kann man nun arbeiten
}


Mit file_exists kann geprüft werden, ob eine Datei bereits existiert, dabei gibt die Funktion entweder eine 1 oder keinen Wert aus.
Hinweis
file_exists kann nur mit dem lokalen Dateisystem arbeiten (Adressen mit http://, ftp:// oder ähnliches wird nicht funktionieren)

$fp=fopen("Datei.txt","r");
$ausgabe=fread($fp,1000);
fclose($fp);


So jetzt mal ein bisschen mehr, um eine Datei zu lesen, benötigt ihr fopen, der erste Parameter ist der Dateiname und der zweite ist die Art des Zugriffes:
r = öffnet die Datei nur zum Lesen (setzt Dateizeiger auf Ende der Datei)
w = öffnet die Datei nur zum Schreiben (setzt Dateizeiger auf Anfang der Datei)
a = öffnet die Datei nur zum Schreiben (setzt Dateizeiger auf Ende der Datei)
+ = optional, fügt bei allen Werten den Schreib- bzw. Lesemodus hinzu
fread wird der Dateizeiger $fp ausgelesen und als String $ausgabe gespeichert, der erste Parameter ist der Dateizeiger $fp und der zweite, wie weit die Datei gelesen werden soll, hier 1000 Bytes. Manche verwenden dafür die Funktion filesize() um die Dateigröße auslesen zu lassen, damit würde die gesamte Datei gelesen. Um eine komplette Datei zu lesen, kann entweder file() oder file_get_contents() verwendet werden.

Wichtig
Um Probleme beim erneuten Öffnen zu vermeiden, müsst ihr immer mit fclose die Datei wieder schließen!

$inhalt_array = file('Datei.txt');
$inhalt = file_get_contents('Datei.txt');


Der Unterschied besteht eigentlich nur darin, dass file ein Array übergibt, womit jede Zeile für sich angesprochen werden kann, im Gegensatz dazu, liest file_get_contents den kompletten Inhalt in einen String, womit direkt gearbeitet werden kann (z.B. per echo ausgeben lassen)
Durch diverse Tests habe ich die Performance der Funktionen file_get_contents sowie file deutlich gemerkt, anstatt diese zwei Funktionen zu nutzen ist es von der Geschwindigkeit her besser per fopen die Daten zu lesen.


Wir möchten nun einen Inhalt in die Datei.txt schreiben, dazu muss unser PHP-Skript aus zwei Teilen bestehen:

Der PHP-Teil besteht zuerst aus einer if-Abfrage, das hat den Grund, wenn wir unser Skript das erstemal aufrufen würde kein Inhalt in die Datei geschrieben.
Als nächstes öffnen wir die Datei mit fopen zum Schreiben (r = read, w = write).
Mit fwrite schreiben wir nun in die Datei, die Funktion benötigt den Dateizeiger von fopen um zu wissen welche Datei geöffnet ist. Als zweiter Parameter wird nun der Inhalt benötigt!
Der letzte Schritt ist immer die Datei wiederzuschließen dazu ist unser fclose nötig.
if($_POST['submit'])
  {
    $fp = fopen ("Datei.txt","w");
    fwrite($fp,$_POST['inhalt']);
    fclose($fp);
  }


Der HTML-Teil enthält das Formular mit einem Textfeld und einen Button zum Absenden. In <form> definieren wir die Methode mit der das Formular versendet wird. Zur Auswahl stehen GET oder POST.
GET-Methode versendet die Daten über die Adresszeile des Browsers, diese Methode wird nicht empfohlen für Formulare. (Ein kleines Beispiel: http://localhost/index.php?inhalt=Mein%20Inhalt&submit=submit)
POST-Methode der Wert wird dem Browser intern mitgeteilt (wie das genau funktioniert würde das Tutorial sprengen), d.h. es kann nicht einfach die Adresszeile geändert werden um das Formular erneut zu senden.
<form method="post" action="">
  <textarea rows="5" cols="40" name="inhalt"></textarea><br />
  <input type="submit" name="submit" value="speichern" />
</form>