PHP 8.4.1 Released!

fopen

(PHP 4, PHP 5, PHP 7, PHP 8)

fopenÖffnet eine Datei oder URL

Beschreibung

fopen(
    string $filename,
    string $mode,
    bool $use_include_path = false,
    ?resource $context = null
): resource|false

fopen() bindet eine benannte Ressource, die durch filename spezifiziert wurde, an einen Stream.

Parameter-Liste

filename

Wenn filename die Form "schema://..." hat, wird angenommen, dass es sich hier um eine URL handelt, und PHP sucht nach einem Protokollhandler (auch als Wrapper bekannt) für dieses Schema. Sind keine Wrapper für dieses Protokoll registriert, gibt PHP einen Hinweis aus, um Ihnen zu helfen, mögliche Probleme in Ihrem Skript zu erkennen, und fährt dann fort, als ob filename eine reguläre Datei spezifiziert.

Ist PHP zu dem Schluss gekommen, dass filename eine lokale Datei spezifiziert, wird es versuchen, einen Stream an dieser Datei zu öffnen. Die Datei muss für PHP zugreifbar sein, weshalb Sie sicherstellen müssen, dass die Dateirechte diesen Zugriff ermöglichen. Wenn Sie open_basedir aktiviert haben, können weitere Einschränkungen gelten.

Kam PHP zum Schluss, dass es sich bei filename um ein registriertes Protokoll handelt, und ist dieses Protokoll als eine Netzwerk-URL registriert, prüft PHP, ob allow_url_fopen aktiviert ist. Ist es nicht aktiviert, gibt PHP eine Warnung aus und der Aufruf von fopen() scheitert.

Hinweis:

Die Liste der unterstützten Protokolle ist unter Unterstützte Protokolle und Wrapper zu finden. Einige Protokolle (auch als Wrapper bezeichnet) unterstützen context und/oder php.ini-Optionen. Eine Liste der verfügbaren Optionen finden Sie auf den Handbuchseiten zum verwendeten Protokoll (z. B. die php.ini-Option user_agent, die vom http-Wrapper verwendet wird).

Es ist darauf zu achten, unter Windows alle Backslash-Zeichen, die in Pfaden genutzt werden, zu maskieren oder Schrägstriche (Slashes) zu nutzen.

<?php
$handle
= fopen("c:\\verzeichnis\\ressource.txt", "r");
?>

mode

Der Parameter mode spezifiziert den Zugriffstyp, der vom Stream gefordert wird. Es kann einer der folgenden sein:

Eine Liste der möglichen Modi von fopen() mittels mode
mode Beschreibung
'r' Nur zum Lesen geöffnet; platziere den Dateizeiger auf den Dateianfang.
'r+' Zum Lesen und Schreiben geöffnet; platziere den Dateizeiger auf den Dateianfang.
'w' Nur zum Schreiben geöffnet; platziere den Dateizeiger auf den Dateianfang und kürze die Datei auf eine Länge von 0. Existiert die Datei nicht, versuche, diese zu erzeugen.
'w+' Zum Schreiben und Lesen geöffnet; ansonsten verhält es sich wie 'w'..
'a' Nur zum Schreiben geöffnet; platziere den Dateizeiger auf das Dateiende. Existiert die Datei nicht, versuche, diese zu erzeugen. In diesem Modus ist fseek() wirkungslos; beim Schreiben wird immer angehängt.
'a+' Zum Schreiben und Lesen geöffnet; platziere den Dateizeiger auf das Dateiende. Existiert die Datei nicht, versuche, diese zu erzeugen. In diesem Modus wirkt sich fseek() nur auf die Leseposition aus; beim Schreiben wird immer angehängt.
'x' Erzeuge und öffne nur zum Schreiben; platziere den Dateizeiger auf den Dateianfang. Falls die Datei schon existiert, wird der fopen()-Aufruf fehlschlagen, indem er false zurückgibt und dem einen Fehler der Stufe E_WARNING auslöst. Existiert die Datei nicht, versuche, diese zu erzeugen. Dies ist zur Angabe der O_EXCL|O_CREAT-Flags für den darunterliegenden open(2)-Systemaufruf äquivalent.
'x+' Erzeuge und öffne zum Schreiben und Lesen; ansonsten ist das Verhalten gleich wie bei 'x'.
'c' Öffne die Datei nur zum Schreiben. Wenn die Datei nicht existiert, wird diese erzeugt. Wenn sie existiert, wird sie weder gekürzt (im Gegensatz zu 'w'), noch schlägt der Aufruf dieser Funktion fehl (wie dies mit 'x' der Fall ist). Der Dateizeiger wird auf den Dateianfang platziert. Dies kann nützlich sein, wenn man eine "beratende" (kooperative) Sperre erhalten möchte (siehe flock()), bevor man versucht, die Datei zu ändern, da die Nutzung von 'w' die Datei kürzen könnte, bevor die Sperre erhalten wurde (falls das Kürzen gewünscht ist, kann ftruncate() genutzt werden, nachdem die Sperre angefragt wurde).
'c+' Öffne Datei zum Lesen und Schreiben; ansonsten ist das Verhalten gleich wie bei 'c'.
'e' Setzt das Flag close-on-exec für den geöffneten Datei-Deskriptor. Nur verfügbar, wenn PHP auf POSIX.1-2008-konformen System kompiliert wurde.

Hinweis:

Verschiedene Betriebssysteme haben unterschiedliche Konventionen für das Zeilenende. Wenn Sie eine Textdatei schreiben und einen Zeilenumbruch einfügen möchten, müssen Sie das/die korrekte(n) Zeilenendezeichen für Ihr Betriebssystem nutzen. Unix-basierte Systeme nutzen \n als Zeilenendezeichen, Windows-basierte Systeme nutzen \r\n als Zeilenendezeichen und Macintosh-basierte Systeme (Mac OS Classic) nutzten \r als Zeilenendezeichen.

Wenn Sie die falschen Zeilenendezeichen beim Schreiben Ihrer Dateien nutzen, kann es sein, dass andere Anwendungen, die diese Dateien öffnen, "seltsam aussehen".

Windows bietet ein Übersetzungs-Flag ('t') fur den Textmodus an, das \n transparent in \r\n übersetzt, wenn mit der Datei gearbeitet wird. Andererseits kann auch 'b' genutzt werden, um den Binärmodus zu erzwingen, der die Daten nicht übersetzt. Um diese Flags zu nutzen, wird entweder 'b' oder 't' als das letzte Zeichen des Parameters mode angegeben.

Der Standard-Übersetzungsmodus ist 'b'. Es kann der Modus 't' genutzt werden, wenn mit Textdateien gearbeitet wird und \n verwendet wird, um die Zeilenenden im Skript zu begrenzen, aber erwartet wird, dass die Dateien mit Anwendungen wie etwa alten Versionen von Notepad lesbar sind. Ansonsten sollte 'b' genutzt werden.

Wird beim Arbeiten mit binären Dateien das Flag 't' angegeben, können seltsame Probleme mit den Daten auftreten, einschließlich zerstörter Bilddateien und merkwürdiger Probleme mit \r\n-Zeichen.

Hinweis:

Aus Portabilitätsgründen wird ebenfalls dringend empfohlen, dass Code, der den Modus 't' nutzt oder sich darauf verlässt, so umgeschrieben wird, dass stattdessen die korrekten Zeilenendungen und der Modus 'b' genutzt werden.

Hinweis: Der Parameter mode wird bei den Stream-Wrappern php://output, php://input, php://stdin, php://stdout, php://stderr und php://fd ignoriert.

use_include_path

Der optionale dritte Parameter use_include_path kann auf true gesetzt werden, wenn auch im include_path nach der Datei gesucht werden soll.

context

Eine Stream-Kontext-Ressource.

Rückgabewerte

Gibt bei Erfolg eine Dateizeiger-Ressource zurück. Bei einem Fehler wird false zurückgegeben.

Fehler/Exceptions

Im Fehlerfall wird eine E_WARNING ausgegeben.

Changelog

Version Beschreibung
7.0.16, 7.1.2 Die Option 'e' wurde hinzugefügt.

Beispiele

Beispiel #1 fopen()-Beispiele

<?php
$handle
= fopen("/home/rasmus/file.txt", "r");
$handle = fopen("/home/rasmus/file.gif", "wb");
$handle = fopen("http://www.example.com/", "r");
$handle = fopen("ftp://user:password@example.com/somefile.txt", "w");
?>

Anmerkungen

Warnung

Bei SSL-Verbindungen zusammen mit Microsoft IIS hält sich dieser Webserver nicht an das Protokoll und schließt die Verbindung ohne ein close_notify zu senden. PHP quittiert dieses Fehlverhalten mit "SSL: Fatal Protocol Error", wenn das Ende der Daten erreicht ist. Eine mögliche Lösung besteht darin, den Level von error_reporting herabzusetzten und Warnings auszuschließen. PHP kann fehlerhafte IIS-Serversoftware erkennen, wenn Sie einen Stream mit dem https://-Wrapper öffnen, und unterdrückt die Warnung für Sie. Falls Sie fsockopen() benutzen, um einen ssl://-Socket zu öffnen, müssen Sie selbst dafür Sorge tragen, die Warnung zu erkennen und diese zu unterdrücken.

Hinweis:

Wenn die Servermodul-Version von PHP wird verwendet wird und beim Lesen und Schreiben von Dateien Probleme auftreten, ist sicherzustellen, dass die Dateien und Verzeichnisse, die genutzt werden, für den Server-Prozess zugänglich sind.

Hinweis:

Diese Funktion kann auch dann funktionieren, wenn filename ein Verzeichnis ist. Im Zweifelsfall sollte vor dem Aufruf von fopen() mit is_dir() geprüft werden, ob filename eine Datei oder ein Verzeichnis ist.

Siehe auch

add a note

User Contributed Notes 21 notes

up
146
chapman at worldtakeoverindustries dot com
12 years ago
Note - using fopen in 'w' mode will NOT update the modification time (filemtime) of a file like you may expect. You may want to issue a touch() after writing and closing the file which update its modification time. This may become critical in a caching situation, if you intend to keep your hair.
up
43
Anon.
4 years ago
/***** GENTLE REMINDER *****/
Really important. Do NOT use the "w" flag unless you want to delete everything in the file.
up
10
php-manual at merlindynamics dot com
4 years ago
There is an undocumented mode for making fopen non-blocking (not working on windows). By adding 'n' to the mode parameter, fopen will not block, however if the pipe does not exist an error will be raised.

$fp = fopen("/tmp/debug", "a"); //blocks if pipe does not exist

$fp = fopen("/tmp/debug", "an"); //raises error on pipe not exist
up
25
php at delhelsa dot com
16 years ago
With php 5.2.5 on Apache 2.2.4, accessing files on an ftp server with fopen() or readfile() requires an extra forwardslash if an absolute path is needed.

i.e., if a file called bullbes.txt is stored under /var/school/ on ftp server example.com and you're trying to access it with user blossom and password buttercup, the url would be:

ftp://blossom:buttercup@example.com//var/school/bubbles.txt

Note the two forwardslashes. It looks like the second one is needed so the server won't interpret the path as relative to blossom's home on townsville.
up
12
petepostma-deletethis at gmail dot com
7 years ago
The verbal descriptions take a while to read through to get a feel for the expected results for fopen modes. This csv table can help break it down for quicker understanding to find which mode you are looking for:

Mode,Creates,Reads,Writes,Pointer Starts,Truncates File,Notes,Purpose
r,,y,,beginning,,fails if file doesn't exist,basic read existing file
r+,,y,y,beginning,,fails if file doesn't exist,basic r/w existing file
w,y,,y,beginning+end,y,,"create, erase, write file"
w+,y,y,y,beginning+end,y,,"create, erase, write file with read option"
a,y,,y,end,,,"write from end of file, create if needed"
a+,y,y,y,end,,,"write from end of file, create if needed, with read options"
x,y,,y,beginning,,fails if file exists,"like w, but prevents over-writing an existing file"
x+,y,y,y,beginning,,fails if file exists,"like w+, but prevents over writing an existing file"
c,y,,y,beginning,,,open/create a file for writing without deleting current content
c+,y,y,y,beginning,,,"open/create a file that is read, and then written back down"
up
12
ideacode
19 years ago
Note that whether you may open directories is operating system dependent. The following lines:

<?php
// Windows ($fh === false)
$fh = fopen('c:\\Temp', 'r');

// UNIX (is_resource($fh) === true)
$fh = fopen('/tmp', 'r');
?>

demonstrate that on Windows (2000, probably XP) you may not open a directory (the error is "Permission Denied"), regardless of the security permissions on that directory.

On UNIX, you may happily read the directory format for the native filesystem.
up
6
splogamurugan at gmail dot com
13 years ago
While opening a file with multibyte data (Ex: données multi-octets), faced some issues with the encoding. Got to know that it uses windows-1250. Used iconv to convert it to UTF-8 and it resolved the issue.

<?php
function utf8_fopen_read($fileName) {
$fc = iconv('windows-1250', 'utf-8', file_get_contents($fileName));
$handle=fopen("php://memory", "rw");
fwrite($handle, $fc);
fseek($handle, 0);
return
$handle;
}
?>

Example usage:

<?php
$fh
= utf8_fopen_read("./tpKpiBundle.csv");
while ((
$data = fgetcsv($fh, 1000, ",")) !== false) {
foreach (
$data as $value) {
echo
$value . "<br />\n";
}
}
?>

Hope it helps.
up
4
durwood at speakeasy dot NOSPAM dot net
19 years ago
I couldn't for the life of me get a certain php script working when i moved my server to a new Fedora 4 installation. The problem was that fopen() was failing when trying to access a file as a URL through apache -- even though it worked fine when run from the shell and even though the file was readily readable from any browser. After trying to place blame on Apache, RedHat, and even my cat and dog, I finally ran across this bug report on Redhat's website:

https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=164700

Basically the problem was SELinux (which I knew nothing about) -- you have to run the following command in order for SELinux to allow php to open a web file:

/usr/sbin/setsebool httpd_can_network_connect=1

To make the change permanent, run it with the -P option:

/usr/sbin/setsebool -P httpd_can_network_connect=1

Hope this helps others out -- it sure took me a long time to track down the problem.
up
3
php at richardneill dot org
13 years ago
fopen() will block if the file to be opened is a fifo. This is true whether it's opened in "r" or "w" mode. (See man 7 fifo: this is the correct, default behaviour; although Linux supports non-blocking fopen() of a fifo, PHP doesn't).
The consequence of this is that you can't discover whether an initial fifo read/write would block because to do that you need stream_select(), which in turn requires that fopen() has happened!
up
2
etters dot ayoub at gmail dot com
6 years ago
This functions check recursive permissions and recursive existence parent folders, before creating a folder. To avoid the generation of errors/warnings.

/**
* This functions check recursive permissions and recursive existence parent folders,
* before creating a folder. To avoid the generation of errors/warnings.
*
* @return bool
* true folder has been created or exist and writable.
* False folder not exist and cannot be created.
*/
function createWritableFolder($folder)
{
if (file_exists($folder)) {
// Folder exist.
return is_writable($folder);
}
// Folder not exit, check parent folder.
$folderParent = dirname($folder);
if($folderParent != '.' && $folderParent != '/' ) {
if(!createWritableFolder(dirname($folder))) {
// Failed to create folder parent.
return false;
}
// Folder parent created.
}

if ( is_writable($folderParent) ) {
// Folder parent is writable.
if ( mkdir($folder, 0777, true) ) {
// Folder created.
return true;
}
// Failed to create folder.
}
// Folder parent is not writable.
return false;
}

/**
* This functions check recursive permissions and recursive existence parent folders,
* before creating a file/folder. To avoid the generation of errors/warnings.
*
* @return bool
* true has been created or file exist and writable.
* False file not exist and cannot be created.
*/
function createWritableFile($file)
{
// Check if conf file exist.
if (file_exists($file)) {
// check if conf file is writable.
return is_writable($file);
}

// Check if conf folder exist and try to create conf file.
if(createWritableFolder(dirname($file)) && ($handle = fopen($file, 'a'))) {
fclose($handle);
return true; // File conf created.
}
// Inaccessible conf file.
return false;
}
up
4
dan at cleandns dot com
21 years ago
<?php
#going to update last users counter script since
#aborting a write because a file is locked is not correct.

$counter_file = '/tmp/counter.txt';
clearstatcache();
ignore_user_abort(true); ## prevent refresh from aborting file operations and hosing file
if (file_exists($counter_file)) {
$fh = fopen($counter_file, 'r+');
while(
1) {
if (
flock($fh, LOCK_EX)) {
#$buffer = chop(fgets($fh, 2));
$buffer = chop(fread($fh, filesize($counter_file)));
$buffer++;
rewind($fh);
fwrite($fh, $buffer);
fflush($fh);
ftruncate($fh, ftell($fh));
flock($fh, LOCK_UN);
break;
}
}
}
else {
$fh = fopen($counter_file, 'w+');
fwrite($fh, "1");
$buffer="1";
}
fclose($fh);

print
"Count is $buffer";

?>
up
4
info at b1g dot de
19 years ago
Simple class to fetch a HTTP URL. Supports "Location:"-redirections. Useful for servers with allow_url_fopen=false. Works with SSL-secured hosts.

<?php
#usage:
$r = new HTTPRequest('http://www.example.com');
echo
$r->DownloadToString();

class
HTTPRequest
{
var
$_fp; // HTTP socket
var $_url; // full URL
var $_host; // HTTP host
var $_protocol; // protocol (HTTP/HTTPS)
var $_uri; // request URI
var $_port; // port

// scan url
function _scan_url()
{
$req = $this->_url;

$pos = strpos($req, '://');
$this->_protocol = strtolower(substr($req, 0, $pos));

$req = substr($req, $pos+3);
$pos = strpos($req, '/');
if(
$pos === false)
$pos = strlen($req);
$host = substr($req, 0, $pos);

if(
strpos($host, ':') !== false)
{
list(
$this->_host, $this->_port) = explode(':', $host);
}
else
{
$this->_host = $host;
$this->_port = ($this->_protocol == 'https') ? 443 : 80;
}

$this->_uri = substr($req, $pos);
if(
$this->_uri == '')
$this->_uri = '/';
}

// constructor
function HTTPRequest($url)
{
$this->_url = $url;
$this->_scan_url();
}

// download URL to string
function DownloadToString()
{
$crlf = "\r\n";

// generate request
$req = 'GET ' . $this->_uri . ' HTTP/1.0' . $crlf
. 'Host: ' . $this->_host . $crlf
. $crlf;

// fetch
$this->_fp = fsockopen(($this->_protocol == 'https' ? 'ssl://' : '') . $this->_host, $this->_port);
fwrite($this->_fp, $req);
while(
is_resource($this->_fp) && $this->_fp && !feof($this->_fp))
$response .= fread($this->_fp, 1024);
fclose($this->_fp);

// split header and body
$pos = strpos($response, $crlf . $crlf);
if(
$pos === false)
return(
$response);
$header = substr($response, 0, $pos);
$body = substr($response, $pos + 2 * strlen($crlf));

// parse headers
$headers = array();
$lines = explode($crlf, $header);
foreach(
$lines as $line)
if((
$pos = strpos($line, ':')) !== false)
$headers[strtolower(trim(substr($line, 0, $pos)))] = trim(substr($line, $pos+1));

// redirection?
if(isset($headers['location']))
{
$http = new HTTPRequest($headers['location']);
return(
$http->DownloadToString($http));
}
else
{
return(
$body);
}
}
}
?>
up
1
apathetic012 at gmail dot com
12 years ago
a variable $http_response_header is available when doing the fopen(). Which contains an array of the response header.
up
1
ken dot gregg at rwre dot com
20 years ago
PHP will open a directory if a path with no file name is supplied. This just bit me. I was not checking the filename part of a concatenated string.

For example:

<?php
$fd
= fopen('/home/mydir/' . $somefile, 'r');
?>

Will open the directory if $somefile = ''

If you attempt to read using the file handle you will get the binary directory contents. I tried append mode and it errors out so does not seem to be dangerous.

This is with FreeBSD 4.5 and PHP 4.3.1. Behaves the same on 4.1.1 and PHP 4.1.2. I have not tested other version/os combinations.
up
-1
kasper at webmasteren dot eu
12 years ago
"Do not use the following reserved device names for the name of a file:
CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1,
LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9. Also avoid these names
followed immediately by an extension; for example, NUL.txt is not recommended.
For more information, see Namespaces"
it is a windows limitation.
see:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
up
-1
wvss at gmail dot com
2 years ago
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<?php
// generiereHostliste.php

function generiereHostliste($file) {

// aus Rechnerliste.csv lesen
$fp = fopen($file, "r");
while(
$row = fgetcsv($fp, 0, ";")) {
$liste[]=[$row[0].";10.16.".$row[1].".".$row[2]];

}
fclose($fp);

// in Hostliste.csv schreiben
$fp = fopen("Hostliste.csv", "w");
foreach(
$liste as $row) {
echo
"<pre>";
print_r($row);
echo
"</pre>";
fputcsv($fp, $row, ";");
}
fclose($fp);
}
// Test
$file = "Rechnerliste.csv";
generiereHostliste($file);

?>
</body>
</html>
up
-2
flobee
18 years ago
download: i need a function to simulate a "wget url" and do not buffer the data in the memory to avoid thouse problems on large files:
<?php
function download($file_source, $file_target) {
$rh = fopen($file_source, 'rb');
$wh = fopen($file_target, 'wb');
if (
$rh===false || $wh===false) {
// error reading or opening file
return true;
}
while (!
feof($rh)) {
if (
fwrite($wh, fread($rh, 1024)) === FALSE) {
// 'Download error: Cannot write to file ('.$file_target.')';
return true;
}
}
fclose($rh);
fclose($wh);
// No error
return false;
}
?>
up
-1
keithm at aoeex dot NOSPAM dot com
23 years ago
I was working on a consol script for win32 and noticed a few things about it. On win32 it appears that you can't re-open the input stream for reading, but rather you have to open it once, and read from there on. Also, i don't know if this is a bug or what but it appears that fgets() reads until the new line anyway. The number of characters returned is ok, but it will not halt reading and return to the script. I don't know of a work around for this right now, but i'll keep working on it.

This is some code to work around the close and re-open of stdin.

<?php
function read($length='255'){
if (!isset(
$GLOBALS['StdinPointer'])){
$GLOBALS['StdinPointer']=fopen("php://stdin","r");
}
$line=fgets($GLOBALS['StdinPointer'],$length);
return
trim($line);
}
echo
"Enter your name: ";
$name=read();
echo
"Enter your age: ";
$age=read();
echo
"Hi $name, Isn't it Great to be $age years old?";
@
fclose($StdinPointer);
?>
up
-4
ceo at l-i-e dot com
18 years ago
If you need fopen() on a URL to timeout, you can do like:
<?php
$timeout
= 3;
$old = ini_set('default_socket_timeout', $timeout);
$file = fopen('http://example.com', 'r');
ini_set('default_socket_timeout', $old);
stream_set_timeout($file, $timeout);
stream_set_blocking($file, 0);
//the rest is standard
?>
up
-1
bohwaz
10 months ago
Please note that you cannot write to a HTTP resource, for example for doing a PUT request.

You will get this error: 'Failed to open stream: HTTP wrapper does not support writeable connections'

To do a PUT you can only populate the 'content' key of the HTTP context, or use Curl instead.
up
-1
Derrick
1 year ago
Opening a file in "r+" mode, and then trying to set the file pointer position with ftruncate before reading the file will result in file data loss, as though you opened the file in "w" mode.

EX:

$File = fopen($FilePath,"r+"); // OPEN FILE IN READ-WRITE

ftruncate($File, 0); // SET POINTER POSITION (Will Erase Data)

while(! feof($File)) { // CONTINUE UNTIL END OF FILE IS REACHED

$Line = fgets($File); // GET A LINE FROM THE FILE INTO STRING
$Line = trim($Line); // TRIM STRING OF NEW LINE
}

ftruncate($File,0); // (Will Not Erase Data)

fclose($File);
To Top