Forpen

Fopen

(PHP 4, PHP 5)

fopen — Opens file or URL

reject note Description

resource fopen ( string $filename , string $mode [, bool $use_include_path = false [, resource $context ]] )

fopen() binds a named resource, specified by filename, to a stream.

reject note Parameters

 

filename
If filename is of the form “scheme://…”, it is assumed to be a URL and PHP will search for a protocol handler (also known as a wrapper) for that scheme. If no wrappers for that protocol are registered, PHP will emit a notice to help you track potential problems in your script and then continue as though filename specifies a regular file.

If PHP has decided that filename specifies a local file, then it will try to open a stream on that file. The file must be accessible to PHP, so you need to ensure that the file access permissions allow this access. If you have enabled safe mode, or open_basedir further restrictions may apply.

If PHP has decided that filename specifies a registered protocol, and that protocol is registered as a network URL, PHP will check to make sure that allow_url_fopen is enabled. If it is switched off, PHP will emit a warning and the fopen call will fail.

Note:

The list of supported protocols can be found in Supported Protocols and Wrappers. Some protocols (also referred to as wrappers) support context and/or php.ini options. Refer to the specific page for the protocol in use for a list of options which can be set. (e.g. php.ini value user_agent used by the http wrapper).

On the Windows platform, be careful to escape any backslashes used in the path to the file, or use forward slashes.

<?php
$handle = fopen("c:\\folder\\resource.txt", "r");
?>
mode
The mode parameter specifies the type of access you require to the stream. It may be any of the following:

A list of possible modes for fopen() using mode
mode Description
‘r’ Open for reading only; place the file pointer at the beginning of the file.
‘r+’ Open for reading and writing; place the file pointer at the beginning of the file.
‘w’ Open for writing only; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it.
‘w+’ Open for reading and writing; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it.
‘a’ Open for writing only; place the file pointer at the end of the file. If the file does not exist, attempt to create it.
‘a+’ Open for reading and writing; place the file pointer at the end of the file. If the file does not exist, attempt to create it.
‘x’ Create and open for writing only; place the file pointer at the beginning of the file. If the file already exists, the fopen() call will fail by returning FALSE and generating an error of level E_WARNING. If the file does not exist, attempt to create it. This is equivalent to specifying O_EXCL|O_CREAT flags for the underlying open(2) system call.
‘x+’ Create and open for reading and writing; otherwise it has the same behavior as ‘x’.
‘c’ Open the file for writing only. If the file does not exist, it is created. If it exists, it is neither truncated (as opposed to ‘w’), nor the call to this function fails (as is the case with ‘x’). The file pointer is positioned on the beginning of the file. This may be useful if it’s desired to get an advisory lock (see flock()) before attempting to modify the file, as using ‘w’ could truncate the file before the lock was obtained (if truncation is desired, ftruncate() can be used after the lock is requested).
‘c+’ Open the file for reading and writing; otherwise it has the same behavior as ‘c’.

Note:

Different operating system families have different line-ending conventions. When you write a text file and want to insert a line break, you need to use the correct line-ending character(s) for your operating system. Unix based systems use \n as the line ending character, Windows based systems use \r\n as the line ending characters and Macintosh based systems use \r as the line ending character.

If you use the wrong line ending characters when writing your files, you might find that other applications that open those files will “look funny”.

Windows offers a text-mode translation flag (‘t’) which will transparently translate \n to \r\n when working with the file. In contrast, you can also use ‘b’ to force binary mode, which will not translate your data. To use these flags, specify either ‘b’ or ‘t’ as the last character of the mode parameter.

The default translation mode depends on the SAPI and version of PHP that you are using, so you are encouraged to always specify the appropriate flag for portability reasons. You should use the ‘t’ mode if you are working with plain-text files and you use \n to delimit your line endings in your script, but expect your files to be readable with applications such as notepad. You should use the ‘b’ in all other cases.

If you do not specify the ‘b’ flag when working with binary files, you may experience strange problems with your data, including broken image files and strange problems with \r\n characters.

Note:

For portability, it is strongly recommended that you always use the ‘b’ flag when opening files with fopen().

Note:

Again, for portability, it is also strongly recommended that you re-write code that uses or relies upon the ‘t’ mode so that it uses the correct line endings and ‘b’ mode instead.

use_include_path
The optional third use_include_path parameter can be set to ‘1’ or TRUE if you want to search for the file in the include_path, too.

context

Note: Context support was added with PHP 5.0.0. For a description of contexts, refer to Streams.

reject note Return Values

Returns a file pointer resource on success, or FALSE on error.

reject note Errors/Exceptions

If the open fails, an error of level E_WARNING is generated. You may use @ to suppress this warning.

reject note Changelog

 

Version Description
4.3.2 As of PHP 4.3.2, the default mode is set to binary for all platforms that distinguish between binary and text mode. If you are having problems with your scripts after upgrading, try using the ‘t’ flag as a workaround until you have made your script more portable as mentioned before
4.3.2 The ‘x’ and ‘x+’ options were added
5.2.6 The ‘c’ and ‘c+’ options were added

reject note Examples

 

Example #1 fopen() examples

<?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");
?>

reject note Notes

WarningWhen using SSL, Microsoft IIS will violate the protocol by closing the connection without sending a close_notify indicator. PHP will report this as “SSL: Fatal Protocol Error” when you reach the end of the data. To work around this, the value of error_reporting should be lowered to a level that does not include warnings. PHP 4.3.7 and higher can detect buggy IIS server software when you open the stream using the https:// wrapper and will suppress the warning. When using fsockopen() to create an ssl:// socket, the developer is responsible for detecting and suppressing this warning.

Note: When safe mode is enabled, PHP checks whether the directory in which the script is operating has the same UID (owner) as the script that is being executed.

If you are experiencing problems with reading and writing to files and you’re using the server module version of PHP, remember to make sure that the files and directories you’re using are accessible to the server process.

reject note See Also

 

fpassthru> <fnmatch


[edit] Last updated: Fri, 13 Jul 2012

reject note add a note add a note User Contributed Notes fopen

chapman at worldtakeoverindustries dot com 09-Mar-2012 07:25

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.

kasper at webmasteren dot eu 10-Feb-2012 08:36

"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

merye at web-graphique dot com 19-Aug-2011 01:10

I had to switch from relative paths to full paths when my web host recently migrated the server onto their hosting cloud.  This used to work for me:

<?php
$fplog = fopen('ipn.log','a');
?>

After the migration, however, I received the following error message:

Warning: fopen(ipn.log) [function.fopen]: failed to open stream: Permission denied in D:\home\server_name\log_test.php on line 21

I had to change the code to the following to get it to work:

<?php
$logfile = $_SERVER['DOCUMENT_ROOT'].'\\ipn.log';
$fplog = fopen($logfile,'a');
?>

php at richardneill dot org 01-Aug-2011 09:39

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!

splogamurugan at gmail dot com 09-Jun-2011 02:13

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.

owltech at larkandowl dot net 06-Feb-2011 11:20

[fopen note]

I have been trying unsuccessfully to upload and read a Mac OS file on a Linux server. Lots of records show up a just one big using only the following:

<?php $fhandle = fopen($file, 'r'); ?>
or
<?php $fhandle = fopen($file, 'rb'); ?>

It does work, however, this way:

<?php
ini_set('auto_detect_line_endings', TRUE);
$fhandle = fopen($file, 'r');
?>

conartist6 at gmail dot com 04-Nov-2010 09:35

In other comments it has been noted that fopen hangs when opening any fifo which is not actively being written to. It has also been noted that it is possible to prevent this behaviour by performing an fopen with the "r+" flags such that PHP keeps a handle open to the fifo itself.

I hereby document that using the "r+" flag on a pipe under Linux (Slackware 13.0 (i486) and PHP 5.2.14) will render PHP unable to read data waiting to be written to the pipe by any other process. As far as I can tell "r+" is not a valid (read: useful) set of flags for fifo pipes.

Brad G 16-Oct-2010 02:10

While adding CFLAGS="-D_FILE_OFFSET_BITS=64" immediately before calling "./configure" on the PHP source will enable support for using fopen() on large files (greater than 2 GB), note that -- if such an installation of PHP is used in conjunction with Apache HTTPD [2.x], Apache will become completely unresponsive even when not serving output from a PHP application.

In order to gain large file support for non-web applications while maintaining the operability of Apache, consider making two distinct PHP installations:  one with the above CFLAGS specified during configuration (for non-web uses), and the other without this flag (for use with Apache).

eyrie88 at gmail dot com 31-Jul-2010 07:39

Be aware that fopen($url) also respects HTTP status headers. If the URL responds with a 1xx, 4xx, or 5xx status code, you will get a "failed to open stream: HTTP request failed!", followed by the HTTP status response. Same goes for file_get_contents($url)...

anfragen at tsgames dot de 27-May-2010 05:54

Since the http-wrapper doesn't support stat() and so you can't use file_exists() for url's, you can simply use a function like this:

<?php
function http_file_exists($url)
{
$f=@fopen($url,"r");
if($f)
{
fclose($f);
return true;
}
return false;
}
?>

te at sky-networx dot de 01-May-2010 11:13

This is my method for loading the file content.

<?php
public static function loadFile($sFilename, $sCharset = 'UTF-8')
{
if (floatval(phpversion()) >= 4.3) {
$sData = file_get_contents($sFilename);
} else {
if (!file_exists($sFilename)) return -3;
$rHandle = fopen($sFilename, 'r');
if (!$rHandle) return -2;

$sData = '';
while(!feof($rHandle))
$sData .= fread($rHandle, filesize($sFilename));
fclose($rHandle);
}
if ($sEncoding = mb_detect_encoding($sData, 'auto', true) != $sCharset)
$sData = mb_convert_encoding($sData, $sCharset, $sEncoding);
return $sData;
}
?>

magnetik at magnetik dot org 21-Jan-2010 06:43

There IS an option to use fopen with a proxy, it's in $context.
No need to recode everything.

Pastix 20-Jan-2010 03:04

If fopen() has been disabled for security reasons, is possible a porting FROM:

<?php
$f=fopen($file,'rb');
$data='';
while(!feof($f))
$data.=fread($f,$size);
fclose($f);
?>

TO:

<?php
$data = file_get_contents($file); // (PHP 4 >= 4.3.0, PHP 5)
?>

and also a porting FROM:

<?php
$f = fopen($file,'wb');
fwrite($f,$content,strlen($content));
fclose($f);
?>

TO:

<?php
$f=file_put_contents($file, $content); // (PHP 5)
?>

For detail read the php manual.

rene 04-Jan-2010 02:43

if fopen() throws a E_WARNING "failed to open stream: HTTP request failed!" at you when opening a valid URL that you know returns data, i advise you to do the following before calling fopen($url,'r'):

<?php
ini_set ('user_agent', $_SERVER['HTTP_USER_AGENT']);
?>

or anyways, set that 'user_agent' with ini_set() to something valid.

thanks, pollita|at|php.net @ http://bugs.php.net/bug.php?id=22937#c64196 , for the clue to this

b dot evieux at gmail dot com 27-Nov-2009 03:28

Hello all. I have had trouble getting files through proxy, and the solution posted above only works if the requested file is also hosted on the proxy server (which is quite unlikely). so I've put together the following functions pfopen & preadfile. they quite work like the replaced fopen & readfile, and will resort to them if no proxy is provided :)

<?php
function preadfile($_url, $_proxy_name = null, $_proxy_port = 4480){
if(is_null($_proxy_name) || LOCAL_TEST){
return readfile($_url);
}else{
$proxy_cont = '';

$proxy_fp = pfopen($_url, $_proxy_name, $_proxy_port);
while(!feof($proxy_fp)) {$proxy_cont .= fread($proxy_fp,4096);}
fclose($proxy_fp);

$proxy_cont = substr($proxy_cont, strpos($proxy_cont,"\r\n\r\n")+4);
echo $proxy_cont;
return count($proxy_cont);
}
}
function pfopen($_url, $_proxy_name = null, $_proxy_port = 4480) {
if(is_null($_proxy_name) || LOCAL_TEST){
return fopen($_url);
}else{
$proxy_fp = fsockopen($_proxy_name, $_proxy_port);
if (!$proxy_fp) return false;
$host= substr($_url, 7);
$host = substr($bucket, 0, strpos($host, "/"));

$request = "GET $_url HTTP/1.0\r\nHost:$host\r\n\r\n";

fputs($proxy_fp, $request);

return $proxy_fp;
}
}
?>

jbud at jbud dot co dot cc 16-Nov-2009 07:41

This is a function for reading or writing to a text file...
The function has three modes, READ, WRITE, and READ/WRITE... READ, returns the text of a file, or returns FALSE if the file isn't found. WRITE creates or overrides a file with the text from the $input string, WRITE returns TRUE or FALSE depending on success or failure. READ/WRITE reads a text file, then writes the string from $input to the end of the file, like WRITE, it returns TRUE or FALSE depending on success or failure.

<?php
function openFile($file, $mode, $input) {
if ($mode == "READ") {
if (file_exists($file)) {
$handle = fopen($file, "r");
$output = fread($handle, filesize($file));
return $output; // output file text
} else {
return false; // failed.
}
} elseif ($mode == "WRITE") {
$handle = fopen($file, "w");
if (!fwrite($handle, $input)) {
return false; // failed.
} else {
return true; //success.
}
} elseif ($mode == "READ/WRITE") {
if (file_exists($file) && isset($input)) {
$handle = fopen($file "r+");
$read = fread($handle, filesize($file));
$data = $read.$input;
if (!fwrite($handle, $data)) {
return false; // failed.
} else {
return true; // success.
}
} else {
return false; // failed.
}
} else {
return false; // failed.
}
fclose($handle);
}
?>
EXAMPLE CALLS:
<php
openFile2("files/text.txt", "WRITE", "Hello World!");
echo openFile2("files/text.txt", "READ"); // OUTPUT > Hello World!
openFile2("files/text.txt", "READ/WRITE", "!!");
echo openFile2("files/text.txt", "READ"); // OUTPUT > Hello World!!!
?>

maxime dot marais at gmail dot com 09-Nov-2009 07:45

Take great care if you project to use both ftp and
compression wrapper within fopened stream to remotely
write a compressed file built on the fly.

This code :

<?php
$resFile = fopen('compress.bzip2://./test.rnd.bz2', 'wb');
for ($i=0; $i < 1000000 ; $i++)
{
fwrite($resFile, chr(rand(255)));
}
fclose($resFile);
?>

will produce a well formed bz2 compressed random content file.

<?php
$resFile =
fopen('compress.bzip2://ftp://ftp.example.com/test.rnd.bz2',
'wb');
for ($i=0; $i < 1000000 ; $i++)
{
fwrite($resFile, chr(rand(255)));
}
fclose($resFile);
?>

will produce a corrupted bz2 compressed random content
file. The file is not really corrupted, it is incomplete. The
tail of the file is not written to the stream, the file is
truncated at the end of complete compressed data block.

Adding fflush($resFile); before closing the file does not fix
this issue.

This problem can be reproduced with PHP 5.2.6 (bundled
with Debian 2.6.26-13lenny2) and may be related to
http://bugs.php.net/bug.php?id=42117.

Mikhail Nemtsev 31-Aug-2009 04:27

As someone has mentioned already, using fopen() in r+ mode overwrites the beginning of the file with new data. So, if you want to append new data to the beginning of the file, do so as follows:
<?php
$filename = "myfile.txt";
//first, obtain the data initially present in the text file
$ini_handle = fopen($filename, "r");
$ini_contents = fread($ini_handle, filesize($filename));
fclose($ini_handle);
//done obtaining initially present data

//write new data to the file, along with the old data
$handle = fopen($filename, "w+");
$writestring = "text to write to file\n" . $ini_contents;
if (fwrite($handle, $writestring) === false) {
echo "Cannot write to text file. <br />";
}
fclose($handle);
?>

gmdebby at gmail dot com 08-Jun-2009 06:49

I was wondering why was added the "x" mode, it works only if the file do not exists, will create it and open it in read only, it's useless !!
But I found something I could do with that.

Here is a little mk_file function.

<?php
function mk_file($filename) {
if(!is_file($filename)) {
fclose(fopen($filename,"x")); //create the file and close it
return true;
} else return false; //file already exists
}
?>

You can improve it, add chmod support etc...

php at delhelsa dot com 24-Jun-2008 12:27

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.

erk_3 at hotmail dot com 12-May-2008 08:48

If you are getting permission denied trying to write/read to a network resource, you have to change the system account that the apache service is runnning on.
However if you are on a domain, you will need to use the user name as:
user@domain.com

If you user the format: domain\username  the service will successfully start, but you will still receive errors trying to access the network resource.

webmaster at myeshop dot fr 26-Apr-2008 07:40

Also a small function useful for backup for example. It's a mixed between the fopen() and the mkdir() functions.

This function opens a file but also make the path recursively where the file is contained. This is helpful for ending to finish with "No such file or directory in" errors

<?php
function fopen_recursive($path, $mode, $chmod=0755){
preg_match('`^(.+)/([a-zA-Z0-9]+\.[a-z]+)$`i', $path, $matches);
$directory = $matches[1];
$file = $matches[2];

if (!is_dir($directory)){
if (!mkdir($directory, $chmod, 1)){
return FALSE;
}
}
return fopen ($path, $mode);
}
?>

jphansen at uga dot edu 22-Feb-2008 07:04

If you open a file with r+ and execute an fwrite(), writing less to the file than what it originally was, it will result in the difference being padded with the end of the file from the previous end of the file. Example:

<?php
// Open file for read and string modification
$file = "/test";
$fh = fopen($file, 'r+');
$contents = fread($fh, filesize($file));
$new_contents = str_replace("hello world", "hello", $contents);
fclose($fh);

// Open file to write
$fh = fopen($file, 'r+');
fwrite($fh, $new_contents);
fclose($fh);
?>

If the end of the file was "abcdefghij", you will notice that the difference in "hello world" and "hello", 6 characters, will be appended to the file, resulting in the new ending: "efghij". To obviate this, fopen() with +w instead, which truncates the file to zero length.

sean downey 09-Feb-2008 12:23

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 :)

info at NOSPAMPLEASE dot c-eagle dot com 08-Oct-2007 06:14

If there is a file that´s excessively being rewritten by many different users, you´ll note that two almost-simultaneously accesses on that file could interfere with each other. For example if there´s a chat history containing only the last 25 chat lines. Now adding a line also means deleting the very first one. So while that whole writing is happening, another user might also add a line, reading the file, which, at this point, is incomplete, because it´s just being rewritten. The second user would then rewrite an incomplete file and add its line to it, meaning: you just got yourself some data loss!

If flock() was working at all, that might be the key to not let those interferences happen - but flock() mostly won´t work as expected (at least that´s my experience on any linux webserver I´ve tried), and writing own file-locking-functions comes with a lot of possible issues that would finally result in corrupted files. Even though it´s very unlikely, it´s not impossible and has happened to me already.

So I came up with another solution for the file-interference-problem:

1. A file that´s to be accessed will first be copied to a temp-file directory and its last filemtime() is being stored in a PHP-variable. The temp-file gets a random filename, ensuring no other process is able to interfere with this particular temp-file.
2. When the temp-file has been changed/rewritten/whatever, there´ll be a check whether the filemtime() of the original file has been changed since we copied it into our temp-directory.
2.1. If filemtime() is still the same, the temp-file will just be renamed/moved to the original filename, ensuring the original file is never in a temporary state - only the complete previous state or the complete new state.
2.2. But if filemtime() has been changed while our PHP-process wanted to change its file, the temp-file will just be deleted and our new PHP-fileclose-function will return a FALSE, enabling whatever called that function to do it again (ie. upto 5 times, until it returns TRUE).

These are the functions I´ve written for that purpose:

<?php
$dir_fileopen = "../AN/INTERNAL/DIRECTORY/fileopen";

function randomid() {
return time().substr(md5(microtime()), 0, rand(5, 12));
}

function cfopen($filename, $mode, $overwriteanyway = false) {
global $dir_fileopen;
clearstatcache();
do {
$id = md5(randomid(rand(), TRUE));
$tempfilename = $dir_fileopen."/".$id.md5($filename);
} while(file_exists($tempfilename));
if (file_exists($filename)) {
$newfile = false;
copy($filename, $tempfilename);
}else{
$newfile = true;
}
$fp = fopen($tempfilename, $mode);
return $fp ? array($fp, $filename, $id, @filemtime($filename), $newfile, $overwriteanyway) : false;
}

function cfwrite($fp,$string) { return fwrite($fp[0], $string); }

function cfclose($fp, $debug = "off") {
global $dir_fileopen;
$success = fclose($fp[0]);
clearstatcache();
$tempfilename = $dir_fileopen."/".$fp[2].md5($fp[1]);
if ((@filemtime($fp[1]) == $fp[3]) or ($fp[4]==true and !file_exists($fp[1])) or $fp[5]==true) {
rename($tempfilename, $fp[1]);
}else{
unlink($tempfilename);
if ($debug != "off") echo "While writing, another process accessed $fp[1]. To ensure file-integrity, your changes were rejected.";
$success = false;
}
return $success;
}
?>

$overwriteanyway, one of the parameters for cfopen(), means: If cfclose() is used and the original file has changed, this script won´t care and still overwrite the original file with the new temp file. Anyway there won´t be any writing-interference between two PHP processes, assuming there can be no absolute simultaneousness between two (or more) processes.

misc at n4te dot com 05-Oct-2007 06:21

The UTF-8 BOM is optional. PHP does not ignore it if it is present when reading UTF-8 encoded data. Here is a function that skips the BOM, if it exists.

<?php
// Reads past the UTF-8 bom if it is there.
function fopen_utf8 ($filename, $mode) {
$file = @fopen($filename, $mode);
$bom = fread($file, 3);
if ($bom != b"\xEF\xBB\xBF")
rewind($file, 0);
else
echo "bom found!\n";
return $file;
}
?>

simon dot allen at swerve dot co dot nz 09-Apr-2007 07:56

using fopen to upload a file through ftp cannot overwrite that file - use curl instead

naidim at gmail dot com 28-Mar-2007 02:54

While PHP does not have a function to insert text into the middle of a file, it is not that complicated to do.

<?php
function addRSSItem($rssFile, $firstItem, $item){
// Backup file
if(!copy($rssFile, 'backup.rss')) die('Backup failed!');
// Store file contents in array
$arrFile = file($rssFile);
// Open file for output
if(($fh = fopen($rssFile,'w')) === FALSE){
die('Failed to open file for writing!');
}
// Set counters
$currentLine = 0;
$cntFile = count($arrFile);
// Write contents, inserting $item as first item
while( $currentLine <= $cntFile ){
if($currentLine == $firstItem) fwrite($fh, $item);
fwrite($fh, $arrFile[$currentLine]);
$currentLine++;
}
// Delete backup
unlink('backup.rss');
}

$data = "    <item>\n<title>$_POST['title]</title>\n".
"        <description>$_POST['description']</description>\n".
"        <pubDate>$_POST['date']</pubDate>\n".
"        <link>http://www.site.com/mp3s/".
basename($_FILES['fullPath']['name'])."</link>".
"        <enclosure url=\"http://www.site.com/mp3s/".
basename($_FILES['fullPath']['name']).
"\" length=\"$_FILES[fullPath][size]\" type=\"audio/mpeg\" />".
"    </item>\n";
addRSSItem('/var/www/html/rss/podcast.rss',20,$data);
?>

andrew at NOSPAM dot neonsurge dot com 09-Feb-2007 06:22

My recent findings on high-performance fopen/fsockopen usage.

Note #1: The performance comparison below regarding curl is obsolete when utilizing certain things in this comment.  My performance tests download and upload about 97% as fast as curl with a custom non-socket blocking HTTP Transport class written for a high performance system in PHP5.

Note #2: fopen and fsockopen have a "feature' that always forces DNS resolution.  Check this code...

<?php for ($i = 0; $i < 50; $i++) {
$errno = $errstr = "";
//$ip = gethostbyname("php.net");  $a = fsockopen($ip,22,$errno,$errstr,10);  //FAST way
$a = fsockopen("php.net",22,$errno,$errstr,10); //SLOW way
$ab = fread($a,4096); unset($a, $ab);
} ?>

fsockopen() and fopen() always force php.net to be resolved every time and in this example above it resolves the name 50 seperate times and does not use the local cache.  To get around this, gethostbyname() does use your local DNS cache properly, it will not try to get the IP from your DNS server 50 times.  The above code for me to a personal server took 87 seconds the fast way, and 5.74 seconds the slow way, a 650% increase.  And this is single-threaded!  ;)

Note #3: I see a lot of notes and people mentioning non-blocking sockets, especially for HTTP transport.  I thought I would share a little from my experience.  First, the above command fsockopen() allows you to specify a timeout, after you check if it's  opened properly (as you should _always_) you just need to...

<?php stream_set_blocking($a,0);?>

From this point on certain considerations must be taken.  Remember you are not blocking anymore, so when you want to write or read a lot of data it will always return to you instantly.  Which is important since you need to check the return value of your writes and reads against how much you expect to read/write.  For reading if you do not know how long it is, checking for EOF works also.

This is in fact a neat feature and state, since you can now make a read/write loop to send/receive a lot of data and check the time/timeout value(s) constantly.  If that timeout is hit you can throw back errors properly to whatever function/method/code called your transport function/class.  The graceful failure with custom shorter failure times allows your application to continue, especially web-based applications where fopen alone and even curl under certain circumstances does not follow your requested timeouts, it will wait a full 60-90 seconds, depending on your OS.

Good ways to test a custom non-blocking timeout supported transport method described above is to make one first, and then transfer a large file with it, and halfway through unplug your network cable.  Curl or fopen/fread/fwrite alone will croak and make your applications wait a full 60-90 seconds, whereas a nice custom class will check if no data has been transferred for 15 seconds (or less!) and will fail gracefully with a error.

If anyone is interested in chatting about this feel free to contact me or add to this comment.

perrog at gmail dot com 21-Jan-2007 04:05

Note: If you have opened the file in append mode ("a" or "a+"), any data you write to the file will always be appended, regardless of the file position. But PHP distinguish between read and write position, and you may freely read at any position, but when you write it will always append at the end.

If you don't want that write restriction, open the file in read-write mode ("r+") and then start by moving the file pointer to the end.

<?php
if (($fp = fopen($filename, "r+") === FALSE) {
// handle error
exit;
}

if (fseek($fp, 0, SEEK_END) === -1) {
// handle error
exit;
}
?>

patryk dot szczyglowski at gmail dot com 20-Sep-2006 07:02

Watch out not to specify empty string as filename. It seems PHP is trying to get data from stdin which may end up in script timeout. It may not be trivial to find.

<?php
$fp = fopen('', 'r'); // wrong
?>

ceo at l-i-e dot com 10-Apr-2006 08:13

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
?>

flobee 14-Jan-2006 07:58

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;
}
?>

info at b1g dot de 24-Oct-2005 04:54

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);
}
}
}
?>

admin at sellchain dot com 17-Oct-2005 07:34

TIP: If you are using fopen and fread to read HTTP or FTP or Remote Files, and experiencing some performance issues such as stalling, slowing down and otherwise, then it's time you learned a thing called cURL.

Performance Comparison:

10 per minute for fopen/fread for 100 HTTP files
2000 per minute for cURL for 2000 HTTP files

cURL should be used for opening HTTP and FTP files, it is EXTREMELY reliable, even when it comes to performance.

I noticed when using too many scripts at the same time to download the data from the site I was harvesting from, fopen and fread would go into deadlock. When using cURL i can open 50 windows, running 10 URL's from each window, and getting the best performance possible.

Just a Tip :)

nefertari at nefertari dot be 20-Sep-2005 05:47

Important note:

You have always to use the real path name for a file with the command fopen [for example: fopen($filename, 'w')], never use a symbolic link, it will not work (unable to open $filename).

durwood at speakeasy dot NOSPAM dot net 06-Sep-2005 11:43

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.

Luiz Miguel Axcar (lmaxcar at yahoo dot com dot br) 17-Aug-2005 01:11

If you are getting message "Warning: fopen(): URL file-access is disabled in the server configuration", you can use function below to get the content from a local or remote file.

Function uses CURL lib, follow the link to get help: http://www.php.net/curl

<?php
/*
* @return string
* @param string $url
* @desc Return string content from a remote file
* @author Luiz Miguel Axcar (lmaxcar@yahoo.com.br)
*/

function get_content($url)
{
$ch = curl_init();

curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_HEADER, 0);

ob_start();

curl_exec ($ch);
curl_close ($ch);
$string = ob_get_contents();

ob_end_clean();

return $string;
}

#usage:
$content = get_content ("http://www.php.net");
var_dump ($content);
?>

ideacode 03-Aug-2005 07:28

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.

abesharp at yahoo dot co dot uk 05-Apr-2005 04:12

This function has a basic implementation of HTTP Digest Authentication (as per RFC 2617) to get a file from a web server which requires digest authentication (as opposed to basic authentication - the difference being that, with basic, your password is sent to the server as plain text, whereas with digest, it is hashed with a server-supplied nonce to protect against sniffing and replay attacks).

You just supply the host (e.g http://www.example.com), the name of the file you want (e.g protected_page.html), and the necessary username and password, and the function returns the contents of the protected file (or the error message that the server sends, if you supplied the wrong credentials).

If the server only supports a QOP of auth-int (rather then auth) this function won't work, but can be easily modified with reference to the RFC at http://www.ietf.org/rfc/rfc2617.txt

<?php
function readHTTPDigestAuthenticatedFile($host,$file,$username,$password)
{
if (!$fp=fsockopen($host,80, $errno, $errstr, 15))
return false;

//first do the non-authenticated header so that the server
//sends back a 401 error containing its nonce and opaque
$out = "GET /$file HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n\r\n";

fwrite($fp, $out);

//read the reply and look for the WWW-Authenticate element
while (!feof($fp))
{
$line=fgets($fp, 512);

if (strpos($line,"WWW-Authenticate:")!==false)
$authline=trim(substr($line,18));
}

fclose($fp);

//split up the WWW-Authenticate string to find digest-realm,nonce and opaque values
//if qop value is presented as a comma-seperated list (e.g auth,auth-int) then it won't be retrieved correctly
//but that doesn't matter because going to use 'auth' anyway
$authlinearr=explode(",",$authline);
$autharr=array();

foreach ($authlinearr as $el)
{
$elarr=explode("=",$el);
//the substr here is used to remove the double quotes from the values
$autharr[trim($elarr[0])]=substr($elarr[1],1,strlen($elarr[1])-2);
}

foreach ($autharr as $k=>$v)
echo("$k ==> $v\r\n");

//these are all the vals required from the server
$nonce=$autharr['nonce'];
$opaque=$autharr['opaque'];
$drealm=$autharr['Digest realm'];

//client nonce can be anything since this authentication session is not going to be persistent
//likewise for the cookie - just call it MyCookie
$cnonce="sausages";

//calculate the hashes of A1 and A2 as described in RFC 2617
$a1="$username:$drealm:$password";$a2="GET:/$file";
$ha1=md5($a1);$ha2=md5($a2);

//calculate the response hash as described in RFC 2617
$concat = $ha1.':'.$nonce.':00000001:'.$cnonce.':auth:'.$ha2;
$response=md5($concat);

//put together the Authorization Request Header
$out = "GET /$file HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n";
$out .= "Cookie: cookie=MyCookie\r\n";
$out .= "Authorization: Digest username=\"$username\", realm=\"$drealm\", qop=\"auth\", algorithm=\"MD5\", uri=\"/$file\", nonce=\"$nonce\", nc=00000001, cnonce=\"$cnonce\", opaque=\"$opaque\", response=\"$response\"\r\n\r\n";

if (!$fp=fsockopen($host,80, $errno, $errstr, 15))
return false;

fwrite($fp, $out);

//read in a string which is the contents of the required file
while (!feof($fp))
{
$str.=fgets($fp, 512);
}

fclose($fp);

return $str;
}

?>

nuno at ideianet dot pt 04-Mar-2005 05:03

In IIS you must add the group Authenticated Users with write and modify permissions in the file where you want to write if you are in a Protected directory (Basic or Digest authentication) and want to write to a file in a Unprotected directory (Anonymous Access) in order to get permission to do that. Otherwise you will get the message: PHP Warning: fopen(x.txt): failed to open stream: Permission denied in c:\web\x\x.php on line 3 PHP Warning: fwrite(): supplied argument is not a valid stream resource in c:\web\x\x.php on line 10

Thomas Candrian tc_ at gmx dot ch 11-Nov-2004 07:35

With this it isn't possible to get data from another port than 80 (and 443) - at least for me. Because of that I've made this function who gets data from every port you want using HTTP:

<?php;
function getcontent($server, $port, $file)
{
$cont = "";
$ip = gethostbyname($server);
$fp = fsockopen($ip, $port);
if (!$fp)
{
return "Unknown";
}
else
{
$com = "GET $file HTTP/1.1\r\nAccept: */*\r\nAccept-Language: de-ch\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)\r\nHost: $server:$port\r\nConnection: Keep-Alive\r\n\r\n";
fputs($fp, $com);
while (!feof($fp))
{
$cont .= fread($fp, 500);
}
fclose($fp);
$cont = substr($cont, strpos($cont, "\r\n\r\n") + 4);
return $cont;
}
}
echo getcontent("www.myhost.com", "81", "/"));
?>

Works fine for me. Had to do this especially for a shoutcast server, which only delivered the HTML-file if the user-agent was given.

pflaume dot NOSPAM at NOSPAM dot gmx dot de 07-Nov-2004 02:31

fopen() and PROXY

I wondered why there is no possibility to use fopen() through a proxy in php. The solution posted above did not work for me.

This little function gets http through a given proxy:

<?php
function proxy_url($proxy_url)
{
$proxy_name = '127.0.0.1';
$proxy_port = 4001;
$proxy_cont = '';

$proxy_fp = fsockopen($proxy_name, $proxy_port);
if (!$proxy_fp)    {return false;}
fputs($proxy_fp, "GET $proxy_url HTTP/1.0\r\nHost: $proxy_name\r\n\r\n");
while(!feof($proxy_fp)) {$proxy_cont .= fread($proxy_fp,4096);}
fclose($proxy_fp);
$proxy_cont = substr($proxy_cont, strpos($proxy_cont,"\r\n\r\n")+4);
return $proxy_cont;
}
?>

justin at redwiredesign dot com 14-Jul-2004 12:03

One thing worth noting is that if you use the fopen command to open an HTTP stream, and the URL you're trying to access is invalid or generates an error response, (i.e. 404 Not found), the fopen call will return false.

Jem Tallon 13-Apr-2004 03:11

If you're using fopen to open a URL that requires authorization, you might need to force a HTTP/1.0 request for it since fopen won't support HTTP/1.1 requests. You can do that by setting your user_agent to one that is known only to support HTTP/1.0 (most webservers will be configured to force HTTP/1.0 for some browsers). Here's what worked for me:

<?php
$returned=URLopen("http://$username:$password@example.com");

function URLopen($url)
{
// Fake the browser type
ini_set('user_agent','MSIE 4\.0b2;');

$dh = fopen("$url",'r');
$result = fread($dh,8192);
return $result;
}
?>

php at gotdoof dot com 03-Apr-2004 08:19

Note that opening a fifo with fopen() will block the php process until data is sent to it. That means any function you have registered as a shutdown function (register_shutdown_function()) will not be called when the user disconnects, and the process will keep running in the background, waiting for input. I know of no way around this, besides using some other means of IPC.

richard dot quadling at carval dot co dot uk 04-Feb-2004 05:04

The issue involving some sites requiring a valid user-agent string when using fopen can easily be resolved by setting the user_agent string in the PHP.INI file.

If you do not have access to the PHP.INI file, then the use of

ini_set('user_agent','Mozilla: (compatible; Windows XP)');

should also work.

The actual agent string is up to you. If you want to identify to the sites that you are using PHP ...

ini_set('user_agent','PHP');

would do.

Regards,

Richard Quadling.

28-Jan-2004 11:34

If you are connecting to your ftp server through a router doing NAT (such as the Zyxel 128L prestige router/bridge we are using) by doing say an <?php fopen("ftp://ftpusername:ftppassword@example.com/".$file_name, "w") ?>, then this could fail. You will get php_hostconnect connection failed error. This is because fopen() function uses a passive ftp connection which the Zyxel router does not support, even though your ftp server may be configured to allow the passive connections which php fopen() function is using. Note that $file_name is the file we want to ftp to the remote server eg could be file.txt.

Thus an alternative would be to do create the file you want in a local directory of your machine or in the webserver where your php files reside eg use fwrite() as documented in the manual. Once you have the $file_name you want to ftp created, do the following:

<?php
ftp_connect($ftp_server);
//which can connect to the ftp server using an active connection.
ftp_login ($conn_id, $ftp_username."@".$ftp_server, $ftp_password);
$fp = fopen($PATH."".$file_name, 'r');
// eg. $fp = fopen("http://www.yourwebsite.com/".$file_name, 'r');
//turn off passive mode transfers
ftp_pasv ($conn_id, false);
//now upload $file_name
ftp_fput($conn_id, $file_name, $fp, FTP_ASCII));
?>

Your file should now be in your ftp server, having used an active connection.

sergiopaternoster at tiscali dot it 27-Nov-2003 05:11

If you want to open large files (more than 2GB) that's what I did and it works: you should recompile your php with the CFLAGS="-D_FILE_OFFSET_BITS=64" ./configure etc... This tells to your compiler (I tested only gcc on PHP-4.3.4 binary on Linux and Solaris) to make the PHP parser binary large file aware. This way fopen() will not give you the "Value too large for defined data type" error message.
God bless PHP
ciao
Sergio Paternoster

ken dot gregg at rwre dot com 25-Nov-2003 03:03

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.

dan at cleandns dot com 19-Nov-2003 11:15

<?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";

?>

phpNO at SPAMperfectweb dot com 31-Jul-2003 01:39

I offer the following script for updating a counter, using methods gleaned from various posts on file operations...

<?php
$counter_file = 'somefile.txt';
clearstatcache();
ignore_user_abort(true);     ## prevent refresh from aborting file operations and hosing file
$fh = fopen($counter_file, 'r+b');     ## use 'r+b' so file can be read and written
if ($fh)
{
if (flock($fh, LOCK_EX))     ## don't do anything unless lock is successful
{
$count = fread($fh, filesize($counter_file));
rewind($fh);
$count++;
fwrite($fh, $count);
fflush($fh);
ftruncate($fh, ftell($fh));     ## better than truncating to 0 before writing, per 04-Mar-2003 comment below
flock($fh, LOCK_UN);
} else echo "Could not lock counter file '$counter_file'";
fclose($fh);
} else  echo "Could not open counter file '$counter_file'";
ignore_user_abort(false);     ## put things back to normal

echo "counter is at $count";
?>

unshift at yahoo dot com 01-Jul-2003 04:58

It seems that fopen() errors when you attempt opening a url starting with HTTP:// as opposed to http:// - it is case sensitive.  In 4.3.1 anyway..."HTTP://", by not matching "http://" will tell the wrapper to look locally.  From the looks of the source, the same goes for HTTPS vs https, etc.

simon at gornall dot net 19-Jun-2003 12:24

If you're having problems with fopen("url...") but you can run 'host url' in a shell window and get the correct lookup, here's why...

This has had me banging my head against it all day - finally I found the answer buried in the bug reports, but figured it should really be more prominent!

The problem happens when you're on an ADSL line with DHCP (like our office)... When the ADSL modem renews the DHCP lease, you can also switch DNS servers, which confuses apache (and hence PHP) - meaning that you can't look up hosts from within PHP, even though you *can* from the commandline.... The short-term solution is to restart apache.

You'll get "php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution in ..." messages as symptoms. Restart apache, and they're gone :-)

Simon

RobNar 17-Jun-2003 08:15

This is an addendum to ibetyouare at home dot com's note about Apache directory permissions.  If you are on a shared host and cannot tweak Apache's permissions directives then you might try setting the same thing in a .htaccess file.  Failing that, if you are having trouble just creating files then  set the directory permissions to allow writing (for whatever directory the file is supposed to be in) and include the following before fopen():

`touch /path/to/myfile/myfile.txt`;

That will usually create a new empty file that you can write to even when fopen fails. - PHP 4.3.0

Jhilton a at t nurv dot us 05-Jun-2003 12:54

Quick tip. If using fopen to make http requests that contain a querystring, it is advised that you urlencode() your values, else characters like @ can make fopen (or whatever wrapper it is using) throw an error.

04-Mar-2003 08:49

To overwrite a file with a new content without deleting it, and without changing the owner or access rights, it's best to not use:

<?php
$file = fopen($filename, 'r+b'); // binary update mode
//...
ftruncate($file, 0);
fwrite($file, $my_stuff);
//...
fclose($file);
?>

but instead the faster one:

<?php
$file = fopen($filename, 'r+b); // binary update mode
//...
rewind($file);
fwrite($file, $my_stuff);
fflush($file);
ftruncate($file, ftell($file));
//...
fclose($file);
?>

The reason is that truncating a file at size 0 forces the OS to deallocate all storage clusters used by the file, before you write your content which will be reallocated on disk.

The second code simply overwrites the existing content where it is already located on disk, and truncates any remaining bytes that may exist (if the new content is shorter than the old content). The "r+b" mode allows access for both read and write: the file can be kept opened after reading it and before rewriting the modified content.

It's particularly useful for files that are accessed often or have a size larger than a few kilobytes, as it saves lots of system I/O, and also limits the filesystem fragmentation if the updated file is quite large.

And this method also works if the file is locked exclusively once opened (but I would rather recommend using another empty file for locking purpose, opened with "a+" access mode, in "/var/lock/yourapp/*" or other fast filesystems where filelocks are easily monitored and where the webserver running PHP is allowed to create and update lock files, and not forgetting to close the lock file after closing the content file).

draconumpb at hotmail dot com 06-Dec-2002 03:37

I just used explode() as an alternative to fscanf, since my only delimiter was | (pipe). I was having problems with it, since I use it in my news-management script. I found that it cut the last variable I was using, $body, a bit short when I posted a long news post. This would've been a real problem for anybody trying to make news posts longer than a paragraph or so.

However, I found that when I used:
<?php list($variable1, $variable2, etc) = explode("|",$data); ?>
it didn't cut any variables short, so.. what I'm really trying to say here is that for people who are experiencing problems with parsing simple files (i.e with only a single, simple delimiter such as : or |) using the unecessarily complex fscanf() and sscanf() functions, explode() is definately the way to go.

<?php
function get_news($filepath, $newsid)
{
$datafile = fopen("$filepath/news/$newsid.txt","r");
$data = fread($datafile, 1000000);
list($author, $email, $date, $subject, $body) = explode("|",$data);
$body = stripslashes("$body");
$subject = stripslashes("$subject");
echo "<a href=\"mailto:$email\">$author</a> -- $date -- $subject<hr>$body<p>";
}
?>

sample file:

AdministratorMax|admin@example.com|Tuesday, March 5th @ 5:45 PM EST|Site Going Down Tomarrow|Well, folks, I\'m sorry to say that the site will indeed be down tomarrow for most of the day. Hang in there.

Output:

<a href="mailto:admin@example.com">AdministratorMax</a> -- Tuesday, March 5th -- Site Going Down Tomarrow<hr>Well, folks, I'm sorry to say that the site will indeed be down tomarrow for most of the day. Hang in there.

Thought that might be useful for anybody making a simple news-management script, ;)

By the way, feel free to correct me if I made any mistakes - I'm at my dad's work where I don't really have a way to check to see if it works or not. However, I use a more complex version of this on my portal project, and it works beautifully.

01-Jul-2002 09:57

Note that if specifying the optional 'b' (binary) mode, it appears that it cannot be the first letter for some unaccountable reason. In other words, "br" doesn't work, while "rb" is ok!

jared at dctkc dot com 22-Apr-2002 01:33

<?php
// HOW TO USE PHP TO WRITE TO YOUR SERIAL PORT: TWO METHODS
$serproxy=true;
if ($serproxy) {
// Use this code in conjunction with SERPROXY.EXE
// (http://www.lspace.nildram.co.uk/freeware.html)
// which converts a Serial stream to a TCP/IP stream
$fp = fsockopen ("localhost", 5331, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)";
} else {
$e = chr(27);
$string  = $e . "A" . $e . "H300";
$string .= $e . "V100" . $e . "XL1SATO";
$string .= $e . "Q1" . $e . "Z";
echo $string;
fputs ($fp, $string );
fclose ($fp);
}
} elseif ($com1) {
// Use this code to write directly to the COM1 serial port
// First, you want to set the mode of the port. You need to set
// it only once; it will remain the same until you reboot.
// Note: the backticks on the following line will execute the
// DOS 'mode' command from within PHP
`mode com1: BAUD=9600 PARITY=N data=8 stop=1 xon=off`;
$fp = fopen ("COM1:", "w+");
if (!$fp) {
echo "Uh-oh. Port not opened.";
} else {
$e = chr(27);
$string  = $e . "A" . $e . "H300";
$string .= $e . "V100" . $e . "XL1SATO";
$string .= $e . "Q1" . $e . "Z";
echo $string;
fputs ($fp, $string );
fclose ($fp);
}
}
?>

15-Mar-2002 06:18

Also if you're server is useing htaccess to authticate users make sure to add the username and password to the http link you're trying to open. I forgot about this and took a while to find.
ie:

fopen("http://user:pass@www.example.com/mypage.php");

php at themastermind1 dot com 23-Oct-2001 10:37

I have found that I can do fopen("COM1:", "r+"); to open the comport in windows. You have to make sure the comport isn't already open or you will get a permission denied.

I am still playing around with this but you have to somehow flush what you send to the comport if you are trying to communicate realtime with a device.

keithm at aoeex dot NOSPAM dot com 31-Jul-2001 05:19

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);
?>

icon at mricon dot com 09-Nov-1999 02:44

If you're running PHP as apache module, it will always write files as "nobody", "www", "httpd", (or whatever user your webserver runs as) unless you specify a different user/group in httpd.conf, or compile apache with suexec support.
However, if you run PHP as a CGI wrapper, you may setuid the PHP executable to whatever user you wish (*severe* security issues apply). If you really want to be able to su to other user, I recommend compiling with suexec support.
AFAIK, PHP can't NOT use SuEXEC if apache does. If PHP is configured as an apache module it will act as whatever user the apache is. If apache SuEXEC's to otheruser:othergroup (e.g. root:root), that's what PHP will write files as, because it acts as a part of apache code. I suggest you double-check your SuEXEC configuration and settings. Note: you can't su to another user within the PHP code -- it has to be an apache directive, either through <VirtualHost>, or through .htaccess. Also note: I'm not sure how it all works (if it works at all) on Win32 platforms.
Check http://www.apache.org to see how it's done.
Anúncios

Deixe um comentário

Faça o login usando um destes métodos para comentar:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: