Navigation
 Startseite
 Fachbücher
 Anzeigenmarkt
 Forum
 Webmaster News
 Script Newsletter
 Kontakt
 Script Installation
 Php
 Php Tutorials
 Webhoster Vergleich
 Impressum

Community-Bereich
 kostenlos Registrieren
 Anmelden
 Benutzerliste

Script Datenbank
 Script Archiv
 Script Top 20
 Screenshots
 Testberichte

Suche
 

Unsere Php Scripts
 Counter Script
 Umfrage Script
 Bilder Upload Script
 Terminverwaltung
 Simple PHP Forum
 RSS Grabber

Script Mods
 phpBB Adsense Mode

Tools und Generatoren
 .htpasswd Generator
 md5 Generator
 base64 Generator
 Markdown to HTML
 Colorpicker
 Unix timestamp Tool
 TLD Liste
 Webkatalog‑Verzeichnis

Partner
 Sprüche Treff

Hosterplus.de
Bekommen Sie Speicherplatz (Webspace), Domains...
https://www.Hosterplus.de
Artfiles.de
Bietet Serviceorientierte...
https://www.Artfiles.de
 
 
 

PHP is_readable() - Lesbarkeit von Dateien prüfen

Sie befinden sich: Home > Php Tutorial > Das is_readable() Tutorial...

Das is_readable() Tutorial für PHP-Entwickler


Eintrag am:  10.03.2024
Hits / Besucher:  1715
Sprache:  Deutsch
Kategorie:  Einsteiger Tutorials
Tutorial Art:  eigenes
Eingetragen von   schubertmedia schubertmedia
 
Beschreibung

Die PHP-Funktion is_readable() prüft, ob eine Datei oder ein Verzeichnis gelesen werden kann. Sie gibt true zurück, wenn der Pfad existiert und die nötigen Leserechte vorhanden sind. In der Praxis ist is_readable() unverzichtbar, bevor Konfigurationsdateien geladen, Uploads verarbeitet oder Verzeichnisse durchsucht werden.

Syntax und Rückgabewerte

Die Funktion erwartet einen Dateipfad als String und gibt einen booleschen Wert zurück:

is_readable(string $filename): bool

is_readable() gibt true zurück, wenn der Pfad existiert und lesbar ist. In allen anderen Fällen gibt sie false zurück. Das umfasst nicht existierende Pfade, fehlende Berechtigungen und Pfade außerhalb der open_basedir-Einschränkung.

<?php

var_dump(is_readable('config.ini'));
// true, wenn Datei existiert und lesbar

var_dump(is_readable('geheim.txt'));
// false, wenn keine Leserechte

var_dump(is_readable('gibt_es_nicht.txt'));
// false, wenn Datei nicht existiert
?>

file_exists() und is_readable() kombinieren

In der Praxis genügt is_readable() allein nicht für eine aussagekräftige Fehlerbehandlung. Wenn is_readable() false zurückgibt, weiß man nicht, ob die Datei fehlt oder ob sie existiert, aber nicht gelesen werden darf. Die Kombination mit file_exists() ermöglicht differenzierte Fehlermeldungen.

<?php

function dateiLesen(string $pfad): string|false
{
if (!file_exists($pfad)) {
echo "Fehler: Datei nicht gefunden.\n";
return false;
}

if (!is_readable($pfad)) {
echo "Fehler: Keine Leseberechtigung.\n";
return false;
}

return file_get_contents($pfad);
}

/* Aufruf */
$inhalt = dateiLesen('config.ini');
if ($inhalt !== false) {
echo "Datei geladen: " . strlen($inhalt) . " Bytes";
}
?>

Dieses Muster ist der empfohlene Weg, um Dateien sicher zu öffnen. Der Nutzer erhält eine klare Rückmeldung, ob die Datei fehlt oder ob ein Berechtigungsproblem vorliegt. Besonders bei Konfigurationsdateien, die mit parse_ini_file() geladen werden, verhindert diese Prüfung kryptische Fehlermeldungen.

Der stat-Cache und clearstatcache()

PHP speichert die Ergebnisse von Dateisystem-Funktionen wie is_readable(), file_exists() und filesize() in einem internen Cache. Das bedeutet: Wenn sich die Berechtigungen einer Datei während der Laufzeit des Scripts ändern, liefert is_readable() weiterhin das alte Ergebnis.

<?php

$datei = 'daten.txt';

var_dump(is_readable($datei)); // false

/*
* Berechtigung ändern
* (z.B. durch ein anderes Script)
*/
chmod($datei, 0644);

/* Liefert IMMER NOCH false (Cache!) */
var_dump(is_readable($datei)); // false

/* Cache leeren */
clearstatcache();

/* Jetzt wird der aktuelle Zustand geprüft */
var_dump(is_readable($datei)); // true
?>

In den meisten Scripts ist der stat-Cache kein Problem, weil sich Berechtigungen selten zur Laufzeit ändern. Wenn aber chmod() oder ein externer Prozess die Rechte ändert, muss clearstatcache() vor dem nächsten is_readable()-Aufruf stehen.

Verzeichnisse und Symlinks prüfen

Was viele nicht wissen: is_readable() funktioniert nicht nur mit Dateien, sondern auch mit Verzeichnissen. Bei einem Verzeichnis prüft die Funktion, ob dessen Inhalt aufgelistet werden kann. Das ist besonders dann nützlich, wenn ein Script Dateien aus einem bestimmten Ordner dynamisch einlesen soll.

<?php

$verzeichnis = '/var/www/uploads';

if (is_readable($verzeichnis)) {
$dateien = scandir($verzeichnis);
echo 'Gefunden: ' . count($dateien) . ' Einträge';
} else {
echo 'Verzeichnis kann nicht gelesen werden.';
}
?>

Bei Symlinks folgt is_readable() dem Link und prüft die Berechtigung des Ziels, nicht die des Links selbst. Zeigt ein Symlink auf eine Datei ohne Leseberechtigung, gibt is_readable() trotzdem false zurück, auch wenn der Link selbst alle Rechte hat.

<?php

$link = '/var/www/config-link.ini';

/* Symlink existiert, aber das Ziel
ist moeglicherweise nicht lesbar */
if (is_link($link) && is_readable($link)) {
echo 'Symlink-Ziel ist lesbar.';
} elseif (is_link($link)) {
echo 'Symlink existiert, Ziel nicht lesbar.';
} else {
echo 'Kein Symlink unter diesem Pfad.';
}
?>

is_readable mit Ausnahmebehandlung - Diagramm

Warum gibt is_readable() false zurück?

Wenn is_readable() unerwartet false liefert, liegt das fast immer an einer der folgenden Ursachen. Diese Checkliste hilft, das Problem systematisch einzugrenzen.

Datei existiert nicht

Der offensichtlichste Grund: Der Pfad ist falsch oder die Datei wurde gelöscht. Eine Prüfung mit file_exists() vor is_readable() macht die Fehlermeldung eindeutig.

Falsche Dateiberechtigungen

Unter Linux benötigt der Webserver-Benutzer (oft www-data oder apache) Lesezugriff auf die Datei. Mit chmod 644 hat der Eigentümer Lese- und Schreibrecht, alle anderen nur Leserecht. Fehlt das Leserecht, hilft chmod() beim Korrigieren.

<?php

$datei = '/var/www/daten/export.csv';

if (!is_readable($datei)) {
/* Berechtigungen im Oktalformat ausgeben */
$perms = fileperms($datei);
echo 'Aktuelle Rechte: ' . decoct($perms & 0777);
}
?>

stat-Cache nicht geleert

Wie im Abschnitt zu clearstatcache() beschrieben: Wenn sich Berechtigungen zur Laufzeit ändern, liefert is_readable() ohne Cache-Reset veraltete Ergebnisse.

open_basedir-Einschränkung

Auf Shared-Hosting-Servern ist die PHP-Direktive open_basedir fast immer gesetzt. Sie schränkt den Dateizugriff auf bestimmte Verzeichnisse ein. Liegt eine Datei ausserhalb dieser Verzeichnisse, gibt is_readable() nicht nur false zurück, sondern erzeugt zusätzlich eine PHP-Warning.

<?php

/* open_basedir-Einschraenkung abfangen */
$datei = '/tmp/externe-datei.txt';

$alterHandler = set_error_handler(
function ($errno, $errstr) {
/* Warning leise abfangen */
return true;
}
);

$lesbar = is_readable($datei);
restore_error_handler();

if (!$lesbar) {
$basedir = ini_get('open_basedir');
if ($basedir !== '') {
echo 'Zugriff durch open_basedir '
. 'eingeschraenkt: ' . $basedir;
}
}
?>

SELinux-Kontext

Auf Servern mit aktivem SELinux (vor allem CentOS und RHEL) kann eine Datei die richtigen Unix-Rechte haben und trotzdem nicht lesbar sein. SELinux prüft zusätzlich den Sicherheitskontext. Im Zweifelsfall hilft auf der Kommandozeile ls -Z datei.txt zur Diagnose.

Plattformunterschiede: Windows vs. Linux

Das Verhalten von is_readable() unterscheidet sich je nach Betriebssystem erheblich. Unter Linux werden die Unix-Berechtigungen (Owner, Group, Other) vollständig ausgewertet. Eine Datei mit chmod 600 ist nur für den Eigentümer lesbar.

Unter Windows hingegen prüft is_readable() lediglich das Readonly-Attribut der Datei. Die differenzierten NTFS-Berechtigungen (ACLs) werden von PHP nicht berücksichtigt. Das bedeutet: Code, der unter Windows problemlos läuft, kann auf einem Linux-Server fehlschlagen, weil dort strengere Berechtigungen gelten.

Wer lokal unter Windows entwickelt und auf Linux deployt, sollte die Berechtigungen daher immer auf dem Zielserver testen. Eine lokale Prüfung mit is_readable() unter Windows allein ist daher kein verlässlicher Indikator für das tatsächliche Verhalten auf dem Produktivserver.

Praxistipps für den Einsatz von is_readable()

In der täglichen PHP-Entwicklung gibt es einige bewährte Vorgehensweisen rund um is_readable(), die den Code robuster und wartbarer machen.

Prüfung vor include und require

Bevor eine Datei per include oder require eingebunden wird, sollte geprüft werden, ob sie überhaupt lesbar ist. Andernfalls bricht require das Script mit einem Fatal Error ab, während include nur eine Warning erzeugt und mit leerem Inhalt weiterarbeitet. Beides ist in Produktionsumgebungen problematisch.

<?php

$modul = __DIR__ . '/module/zahlungen.php';

if (file_exists($modul) && is_readable($modul)) {
require $modul;
} else {
error_log('Modul nicht ladbar: ' . $modul);
/* Fallback oder Fehlermeldung */
}
?>

Mehrere Dateien gleichzeitig prüfen

Wenn ein Script mehrere Konfigurationsdateien benötigt, lohnt sich eine Schleife, die alle Dateien vorab prüft und fehlende sammelt.

<?php

$dateien = [
__DIR__ . '/config/app.ini',
__DIR__ . '/config/database.ini',
__DIR__ . '/config/mail.ini',
];

$fehlend = [];
foreach ($dateien as $datei) {
if (!is_readable($datei)) {
$fehlend[] = basename($datei);
}
}

if (count($fehlend) > 0) {
die('Fehlende Konfigurationsdateien: '
. implode(', ', $fehlend));
}
?>

Log-Dateien vor dem Lesen prüfen

Log-Dateien können sehr gross werden. Vor dem Einlesen empfiehlt sich neben der Lesbarkeitsprüfung auch eine Grössenprüfung mit filesize(), um den Speicherverbrauch im Blick zu behalten.

<?php

$logDatei = '/var/log/app/fehler.log';

if (!is_readable($logDatei)) {
echo 'Log-Datei nicht lesbar.';
} else {
$groesse = filesize($logDatei);
/* Maximal 5 MB einlesen */
$maxBytes = 5 * 1024 * 1024;

if ($groesse > $maxBytes) {
/* Nur die letzten 5 MB lesen */
$fp = fopen($logDatei, 'r');
fseek($fp, -$maxBytes, SEEK_END);
$inhalt = fread($fp, $maxBytes);
fclose($fp);
} else {
$inhalt = file_get_contents($logDatei);
}

echo 'Log geladen: '
. number_format($groesse) . ' Bytes';
}
?>

Caching-Strategie mit is_readable()

Bei Cache-Dateien wird is_readable() häufig zusammen mit filemtime() verwendet, um zu prüfen, ob ein Cache noch gültig ist.

<?php

$cacheFile = __DIR__ . '/cache/produkte.json';
$maxAlter = 3600; // 1 Stunde

$cacheGueltig = is_readable($cacheFile)
&& (time() - filemtime($cacheFile)) < $maxAlter;

if ($cacheGueltig) {
$daten = json_decode(
file_get_contents($cacheFile), true
);
} else {
/* Daten neu laden und cachen */
$daten = ladeProdukteAusDatenbank();
file_put_contents(
$cacheFile, json_encode($daten)
);
}
?>

Vergleich: is_readable() vs. file_exists() vs. is_file()

PHP bietet mehrere Funktionen zur Dateiprüfung, die sich in ihrem Fokus unterscheiden. Die folgende Tabelle zeigt auf einen Blick, was jede Funktion prüft und wann sie die richtige Wahl ist.

FunktionPrüft ExistenzPrüft TypPrüft BerechtigungTypischer Einsatz
file_exists()JaNeinNeinExistiert der Pfad (Datei oder Verzeichnis)?
is_file()JaNur DateienNeinIst es eine reguläre Datei (kein Verzeichnis)?
is_readable()ImplizitNeinLeserechtKann die Datei geöffnet und gelesen werden?
is_writable()ImplizitNeinSchreibrechtKann in die Datei geschrieben werden?

file_exists() prüft nur die Existenz, sagt aber nichts über Berechtigungen. is_file() stellt sicher, dass es sich um eine Datei handelt und nicht um ein Verzeichnis. is_readable() geht einen Schritt weiter und prüft zusätzlich die Leseberechtigung. In der Praxis kombiniert man diese Funktionen je nach Anforderung.

Praxisbeispiel: Konfigurationsdatei sicher laden

Das folgende Beispiel zeigt einen robusten Ansatz, um eine Konfigurationsdatei zu laden. Es kombiniert mehrere Prüfungen und gibt bei jedem Fehlerfall eine spezifische Meldung aus.

<?php

function ladeKonfiguration(string $pfad): array
{
if (!file_exists($pfad)) {
throw new RuntimeException(
'Konfigurationsdatei nicht gefunden: '
. $pfad
);
}

if (!is_file($pfad)) {
throw new RuntimeException(
'Pfad ist keine Datei: ' . $pfad
);
}

if (!is_readable($pfad)) {
throw new RuntimeException(
'Keine Leseberechtigung: ' . $pfad
);
}

$config = parse_ini_file($pfad, true);

if ($config === false) {
throw new RuntimeException(
'Konfigurationsdatei fehlerhaft: '
. $pfad
);
}

return $config;
}

/* Verwendung */
try {
$config = ladeKonfiguration(
__DIR__ . '/config.ini'
);
echo 'DB-Host: ' . $config['database']['host'];
} catch (RuntimeException $e) {
error_log($e->getMessage());
echo 'Konfiguration konnte nicht '
. 'geladen werden.';
}
?>

Dieses Muster lässt sich auf beliebige Dateitypen übertragen. Ob JSON, XML oder CSV: Die dreistufige Prüfung mit file_exists(), is_file() und is_readable() stellt sicher, dass der eigentliche Lesevorgang nicht an vermeidbaren Fehlern scheitert.

Upload-Verzeichnis validieren

Ein weiteres Praxisbeispiel: Bevor ein Script hochgeladene Dateien verarbeitet, sollte es prüfen, ob das Upload-Verzeichnis überhaupt lesbar ist.

<?php

$uploadDir = __DIR__ . '/uploads';

if (!is_dir($uploadDir)) {
die('Upload-Verzeichnis existiert nicht.');
}

if (!is_readable($uploadDir)) {
die('Upload-Verzeichnis nicht lesbar.');
}

if (!is_writable($uploadDir)) {
die('Upload-Verzeichnis nicht beschreibbar.');
}

/* Alle Bilder im Verzeichnis auflisten */
$bilder = glob($uploadDir . '/*.{jpg,png,webp}',
GLOB_BRACE
);
echo count($bilder) . ' Bilder gefunden.';
?>

Häufige Fragen zu is_readable()

Funktioniert is_readable() auch mit URLs?

Nein. is_readable() arbeitet ausschliesslich mit lokalen Dateipfaden. Ein Aufruf wie is_readable('https://example.com/datei.txt') gibt immer false zurück. Für Remote-Dateien muss stattdessen eine HTTP-Anfrage gesendet werden, etwa mit file_get_contents() in Kombination mit einem Stream-Context oder mit cURL.

Ändert is_readable() die Datei?

Nein. Die Funktion liest die Datei nicht und verändert sie auch nicht. Sie fragt lediglich das Betriebssystem nach den aktuellen Berechtigungen. Der Aufruf ist daher sehr schnell und hat keine Nebenwirkungen auf den Dateiinhalt.

Kann is_readable() mit relativen Pfaden umgehen?

Ja, relative Pfade werden relativ zum aktuellen Arbeitsverzeichnis aufgelöst. In der Praxis ist es aber sicherer, absolute Pfade zu verwenden, zum Beispiel mit __DIR__ als Basis. So vermeidet man Probleme, wenn das Arbeitsverzeichnis unerwartet ein anderes ist.

<?php

/* Unsicher: abhaengig vom Arbeitsverzeichnis */
$unsicher = is_readable('config/app.ini');

/* Sicher: absoluter Pfad */
$sicher = is_readable(
__DIR__ . '/config/app.ini'
);
?>

Was passiert bei leeren Strings?

Ein Aufruf von is_readable('') gibt false zurück. Seit PHP 8.1 erzeugt ein leerer String zusätzlich eine Deprecation-Notice. Ab PHP 9.0 wird dies voraussichtlich einen TypeError auslösen. Es empfiehlt sich daher, den Pfad vor dem Aufruf auf einen leeren String zu prüfen.

Zusammenfassung

is_readable() ist eine unverzichtbare Funktion, wenn ein PHP-Script Dateien öffnen oder Verzeichnisse auflisten muss. Die wichtigsten Punkte:

is_readable() prüft Existenz und Leseberechtigung in einem Schritt. Für differenzierte Fehlermeldungen lohnt sich trotzdem die Kombination mit file_exists(). Der stat-Cache kann veraltete Ergebnisse liefern, deshalb bei Berechtigungsänderungen zur Laufzeit immer clearstatcache() aufrufen. Unter Windows und Linux verhält sich die Funktion unterschiedlich, was beim Deployment beachtet werden muss. Und auf Shared-Hosting-Servern kann open_basedir den Zugriff zusätzlich einschränken.

Als Faustregel gilt: Vor jedem fopen(), include oder file_get_contents() gehört eine Prüfung mit file_exists() und is_readable(). Das kostet wenige Mikrosekunden, erspart aber kryptische Fehlermeldungen und macht den Code für andere Entwickler sofort verständlich.

Wer mit Dateien und Verzeichnissen arbeitet, findet in den verwandten Tutorials zu is_writable(), chmod() und parse_ini_file() weitere nützliche Informationen.

 

Tags:

 

Bücherregal mit drei Büchern: 'PHP 4 - Grundlagen und Profiwissen' von Hanser Verlag, 'Webdesign in a Nutshell' von O'Reilly Verlag, und 'Webgestaltung' von Galileo Computing.