Forum Moderators: coopster

Message Too Old, No Replies

Trouble emulating c+ file mode, appending to begining of file.

Attempting to create a flat-file log.

         

JAB Creations

2:34 am on Jul 13, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I've been attempting to create a flat-file log. My goal has been to append a string from PHP to the beginning if the file. In the example I'm trying to create every time you reload the page the new time stamp is inserted at the top while the existing time stamps are retained below.

The first problem is that the c+ doesn't work either on PHP 5.2.16 or 5.3.0 which is what I have to work with. I haven't been able to determine what the problem is, only that I can't read from the file using c+ and contrary to php.net's documentation when trying to write to a file the mode truncates the file AND in both versions of PHP I have to work with! I'm having the same problems on both Linux and Windows.

So I decided to try to manually emulate the c+ mode by writing a long-winded version. Unfortunately it does some pretty whacky stuff. I can't even figure out how I got it to work that far. Some help would be greatly appreciated.

- John

<?php
$body = '<div>'.date('H:i:s').'</div>'."\n";

$file = 'log11.html';
$result1 = fopen($file,'a+');

if ($result1)
{
$result2 = fread($result1,filesize($file));

if ($result2)
{
$append = $body.$result2;
fclose($result1);

$result3 = $result1 = fopen($file,'w');

if ($result3)
{
$result4 = fwrite($result3,$append);

if ($result4)
{
fclose($result1);
$result5 = fopen($file,'r+');

if ($result5)
{
$result6 = fread($result5,filesize($file));

if ($result6)
{
echo $result6;
}
else {echo 'error 5';}
}
else {echo 'error 5';}
}
else {echo 'error 4';}
}
else {echo 'error 3';}
}
else {echo 'error 2';}
}
else {echo 'error 1';}
?>

StoutFiles

3:13 am on Jul 13, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



To append to the beginning of a file, you create a new file and put the content you want to add first, then the content of the old file in the new one.

<?php
$data = "New stuff!"; //declare the new data to be appended
$new_data .= file_get_contents('olddata.txt'); //appends new content to old content in a variable
file_put_contents('olddata.txt', $data); //erases file info and replaces it with the variable
?>

JAB Creations

12:47 am on Jul 14, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks for your reply Stout, your suggestion works great (had to edit it a little though). ;)

<?php

$data = '<div>'.date('H:i:s').'</div>'."\n";
$data .= file_get_contents('log11.html');
file_put_contents('log11.html',$data);

?>


I took a second shot at trying to get this to work however it overwrites the first line and keeps all the other lines in tact below it. Adding a \n line break on Windows XP to the end of the $body variable interfered with the second line and broke the XHTML which was odd.

<?php

$file = 'log11.html';
$result1 = fopen($file,'c');

if ($result1)
{
$body = '<div>'.date('H:i:s').'</div>';
$result2 = fwrite($result1,$body);

if ($result2)
{
fclose($result1);
$result3 = fopen($file,'r');

if ($result3)
{
$result4 = fread($result3,filesize($file));

if ($result4)
{
echo $result4;
}
else {echo 'error 4';}
}
else {echo 'error 3';}
}
else {echo 'error 2';}
}
else {echo 'error 1';}

?>


Here is the elongated though working version of what the above should be doing...

- John

$body = '<div>'.date('H:i:s').'</div>'."\n";

$file = 'log11.html';
$result1 = fopen($file,'a+');

if ($result1)
{
$result2 = fread($result1,filesize($file));

if ($result2)
{
$append = $body.$result2;
fclose($result1);

$result3 = $result1 = fopen($file,'w');

if ($result3)
{
$result4 = fwrite($result3,$append);

if ($result4)
{
fclose($result1);
$result5 = fopen($file,'r+');

if ($result5)
{
$result6 = fread($result5,filesize($file));

if ($result6)
{
echo $result6;
}
else {echo 'error 5';}
}
else {echo 'error 5';}
}
else {echo 'error 4';}
}
else {echo 'error 3';}
}
else {echo 'error 2';}
}
else {echo 'error 1';}

penders

12:11 am on Jul 16, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I was just having a play with this... It would seem that StoutFiles method is the only way to get this to work.

I took a second shot at trying to get this to work however it overwrites the first line and keeps all the other lines in tact below it. Adding a \n line break on Windows XP to the end of the $body variable interfered with the second line and broke the XHTML which was odd.


Regardless of which (write) mode has been passed to fopen(), fwrite() will always overwrite continuous bytes from the current file pointer. There is no finsert() or equivalent function (that I can see) that will insert at the current file pointer - probably a technical nightmare thinking about it. Line breaks are just additional bytes in the file - there is no concept of 'lines' when reading or writing with fread() and fwrite(). If the first 'line' is 10 bytes followed by a line break and you write 15 chars at the beginning of the file you'll simply end up overwriting the line break and the first 2 'lines' effectively become one.

JAB Creations

12:19 am on Jul 16, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Penders, then I imagine that those working with lines in flat files probably make use of exploding line breaks. That way it's implemented is doubtlessly poor design and highly unintuitive which generally goes against how most of PHP seems to usually work. In the end I'm using a modified version of StoutFiles's suggestion for which I'm grateful works. :)

I'm using this only as a last resort manner to record MySQL errors when a query fails for whatever reason and the database goes down. I had attempted to implement a way to have the script email me and deal with the scenario of unintentional mass-emails though it did not prove reliable enough hence the flat file manner of recording errors.

- John

penders

12:43 am on Jul 16, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



then I imagine that those working with lines in flat files probably make use of exploding line breaks.


Indeed, or use PHP's file() [uk.php.net] function which does this for you. Either way, if you're doing anything more than appending to the end of the file you need to read and write the file in its entirety it seems. Most logging functions (including PHP's error_log() [uk.php.net]) will append to the end of the file.

I think if you want your results in 'reverse' order then I'd leave this to your reporting function. Since you generally want to be able to write to your log as quickly as possible, reading isn't quite so important.