fopen

(PHP 4, PHP 5, PHP 7)

fopenOtwiera plik lub URL

Opis

fopen ( string $nazwa_pliku , string $tryb [, bool $użyj_include_path [, resource $kontekst ]] ) : resource

fopen() wiąże nazwany zasób, określony przez nazwa_pliku, do strumienia.

Parametry

nazwa_pliku

Jeśli nazwa_pliku jest w postaci "schemat://...", to przypuszczalnie jest to URL i PHP szuka protokołu obsługi (także zwanego wrapper'em) dla tego schematu. Jeśli nie zarejestrowano żadnego wrapper'a dla tego protokołu, PHP wyemituje notatkę, aby pomóc Tobie w wyśledzeniu potencajalnego problemu w Twoim skrypcie następnie będzie kontynuować z podanym nazwa_pliku traktując go jako zwykły plik.

Jeśli PHP zdecyduje, że nazwa_pliku określa lokalny plik, wtedy spróbuje otworzyć strumień na tym pliku. Plik musi być dostępny dla PHP, więc musisz zapewnić prawa dostępu do pliku pozwalające na taką operację. Jeśli masz włączone tryb bezpieczny lub open_basedir mogą mieć zastosowanie dodatkowe restrykcje.

Jeśli PHP zdecyduje, że nazwa_pliku określa zarejestrowany protokół i ten protokół jest zarejestowany jako sieciowy URL, PHP sprawdzi allow_url_fopen czy jest włączone. Jeśli jest wyłączone (off), PHP wyświetli ostrzeżenie i wywołanie fopen zakończy się niepowodzeniem.

Informacja:

Listę obsługiwanych protokołów możesz znaleźć w Wspierane protokoły i wrappery. Niektóre protokoły (również określane przez wrappery obsługują kontekst lub/i opcje php.ini. Odwołaj się do konkretnej strony protokołu aby uzyskać listę opcji jakie mogą zostać ustawione (np. php.ini wartość user_agent używana przez wrapper http).

Na platformie Windows, dbaj aby wstawiać znaki ucieczki (escape) przed wszystkimi lewymi ukośnikami (backslash) użytymi w ścieżce do pliku lub używać ukośników (slash).

<?php
$handle 
fopen("c:\\data\\info.txt""r");
?>

tryb

Parametr tryb określa rodzaj dostępu jaki wymagasz do strumienia. Może być dowolny z następujących:

Lista możliwych trybów dla fopen() używając tryb
tryb Opis
'r' Otwiera tylko do odczytu; umieszcza wskaźnik pliku na jego początku.
'r+' Otwiera do odczytu i zapisu; umieszcza wskaźnik pliku na jego początku.
'w' Otwiera tylko do zapisu; umieszcza wskaźnik pliku na jego początku i obcina plik do zerowej długości. Jeśli plik nie istnieje to próbuje go utworzyć.
'w+' Otwiera do odczytu i zapisu; umieszcza wskaźnik pliku na jego początku i obcina plik do zerowej długości. Jeśli plik nie istnieje to próbuje go utworzyć.
'a' Otwiera tylko do zapisu; umieszcza wskaźnik pliku na jego końcu. Jeśli plik nie istnieje to próbuje go utworzyć.
'a+' Otwiera do odczytu i zapisu; umieszcza wskaźnik pliku na jego końcu. Jeśli plik nie istnieje to próbuje go utworzyć.
'x' Tworzy i otwiera plik tylko do zapisu; umieszcza wskaźnik pliku na jego początku. Jeśli plik juz istnieje, wywołanie fopen() nie powiedzie się, zwróci FALSE i wygeneruje błąd na poziomie E_WARNING. Jeśli plik nie istnieje, spróbuje go utworzyć. To jest równoważne z określeniem flag O_EXCL|O_CREAT stosowanym w wywołaniu systemowym open(2).
'x+' Tworzy i otwiera plik odczytu i zapisu; umieszcza wskaźnik pliku na jego początku. Jeśli plik juz istnieje, wywołanie fopen() nie powiedzie się, zwróci FALSE i wygeneruje błąd na poziomie E_WARNING. Jeśli plik nie istnieje, spróbuje go utworzyć. To jest równoważne z okresleniem flag O_EXCL|O_CREAT stosowanym w wywołaniu systemowym open(2).

Informacja:

Różne rodziny systemów operacyjnych stosuja rózne konwencje końca lini. Kiedy zapisujesz plik tekstowy i chcesz wstawić łamanie lini, musisz użyć poprawnych dla twojego systemu operacyjnego znak(ów) końca lini. Systemy bazujące na Uniksie używają \n jako znaku końca lini, systemy bazujące na Windowsie używają \r\n jako znaków końca lini, a systemy Macintosh używają \r jako znak końca lini.

Jeśli użyjesz nieprawidłowego końca lini do zapisu pliku, możesz zaobserwować, w innych aplikacjach otwierając ten plik, że "wygląda on zabawnie".

Windows oferuje flagę ('t') konwertującą tryb tekstowy, która przezroczyście przekłada \n na \r\n kiedy pracujesz z plikiem. Dla kontrastu, możesz także uzyć 'b' aby wymusić tryb binarny, wtedy nie będzie konwertować twoich danych. Aby użyć tych flag, wstaw 'b' lub 't' jako ostatni znak w parametrze tryb.

Domyślnie tryb konwersji zależy od SAPI i wersji PHP jakiej używasz, więc namawiamy aby zawsze podawać stosowną flage w celu przenośności. Powinieneś użyć trybu 't' jeśli pracujesz ze zwykłymi plikami tekstowymi (plain-text)i używasz \n do ograniczenia konców lini w twoim skrypcie, ale wymagasz aby twój plik był czytelny w aplikacjach takich jak notatnik. Powinieneś uzyć 'b' w każdym innym przypadku.

Jeśli nie podasz flagi 'b' kiedy pracujesz na binarnych plikach, możesz doświadczyć dziwnych problemów z twoimi danymi, włączając uszkodzone pliki graficzne i dziwne problemy ze znakami \r\n.

Informacja:

Dla przenośności, bardzo zalecane jest użycie zawsze flagi 'b' kiedy otwierasz pliki za pomocą fopen().

Informacja:

Ponownie, dla przenośności, jest również bardzo zalecane abyś, przepisał swój kod, który używa lub polega na trybie 't' tak aby używał poprawnego końca lini oraz trybu 'b'.

użyj_include_path

Opcjonalny trzeci parametr użyj_include_path może być ustawiony na '1' lub TRUE jeśli chcesz szukać pliku także w include_path.

kontekst

Informacja: Obsługa kontekstów została dodana w PHP 5.0.0. Opis kontekstów znajduje się w rozdziale Streams.

Zwracane wartości

Zwraca wskaźnik pliku do zasobu w przypadku sukcesu lub FALSE przy błędzie.

Błędy/Wyjątki

Jeśli otwieranie się nie powiedzie, funkcja wygeneruje błąd na poziomie E_WARNING. Możesz użyć @ aby zatuszować to ostrzeżenie.

Rejestr zmian

Wersja Opis
4.3.2 Od PHP 4.3.2 domyślny tryb ustawiany jest na binarny, dla wszystkich platform, które rozróżniają tryby binarne i tekstowe. Jeśli masz problemy ze skryptem po aktualizacji, spróbuj użyć flagi 't' jako obejście dopóki nie uczynisz Twojego skryptu bardziej przenośnym jak opisano niżej.
4.3.2 Dodano opcje 'x' i 'x+'

Przykłady

Przykład #1 fopen() przykłady

<?php
$handle 
fopen("/home/rasmus/plik.txt""r");
$handle fopen("/home/rasmus/plik.gif""wb");
$handle fopen("http://www.przyklad.com/""r");
$handle fopen("ftp://uzytkownik:haslo@przyklad.com/jakisplik.txt""w");
?>

Notatki

Ostrzeżenie

Nawiązując połączenie przez SSL, serwer Microsoft IIS narusza reguły protokołu przez zamknięcie połączenia bez wysłania wskaźnika close_notify. Po przesłaniu całości danych PHP zgłosi to jako "SSL: Fatal Protocol Error". Aby obejść ten błąd, wystarczy obniżyć poziom raportowania błędów error_reporting, tak aby nie były wyświetlane ostrzeżenia. PHP sam wykrywa błąd serwera IIS przy otwieraniu strumienia https:// i za pomocą nakładki i pomijają ostrzeżenia. Używając funkcji fsockopen() do otwarcia gniazda ssl:// programista sam musi zadbać o wyłączenie ostrzeżeń.

Informacja: Gdy włączony jest tryb bezpieczny, PHP sprawdza czy katalog, na którym zostaną wykonane operacje, ma takie same UID (owner) jak skrypt, który jest aktualnie wykonywany.

Jeśli doświadczasz problemów z odczytem lub zapisywaniem do plików i używasz PHP w postaci modułu serwera, pamiętaj, żeby się upewnić, że pliki i katalogi, których używasz są dostępne dla procesu serwera.

Zobacz też:

add a note add a note

User Contributed Notes 20 notes

up
113
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
3
php-manual at merlindynamics dot com
3 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
21
php at delhelsa dot com
15 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
6
petepostma-deletethis at gmail dot com
6 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
3
Anon.
3 years ago
/***** GENTLE REMINDER *****/
Really important. Do NOT use the "w" flag unless you want to delete everything in the file.
up
4
durwood at speakeasy dot NOSPAM dot net
18 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
5
ideacode
18 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
8
info at b1g dot de
18 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
k-gun at git dot io
4 years ago
Seems not documented here but keep in mind, when $filename contains null byte (\0) then a TypeError will be thrown with message such;

TypeError: fopen() expects parameter 1 to be a valid path, string given in ...
up
3
ceo at l-i-e dot com
17 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
2
keithm at aoeex dot NOSPAM dot com
22 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
1
php at richardneill dot org
12 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
dan at cleandns dot com
20 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
1
apathetic012 at gmail dot com
11 years ago
a variable $http_response_header is available when doing the fopen(). Which contains an array of the response header.
up
0
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
1
splogamurugan at gmail dot com
12 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
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
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
-2
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
-4
sean downey
16 years ago
when using ssl / https on windows i would get the error:
"Warning: fopen(https://example.com): failed to open stream: Invalid argument in someSpecialFile.php on line 4344534"

This was because I did not have the extension "php_openssl.dll" enabled.

So if you have the same problem, goto your php.ini file and enable it :)
To Top