Connecting Tech Pros Worldwide Forums | Help | Site Map

Reading from file basics

deko
Guest
 
Posts: n/a
#1: Jul 17 '05
Is there a way to avoid opening and closing the file "viscount" twice in this
code:

<?php
$file = 'viscount.txt';
if ($counter = @file ($file)) {
$line = each($counter);
if (!$counter) {
$counter = 1;
} else {
$counter = $line[value]+1;
}
}
$fp = fopen ($file, "w");
fwrite ($fp, "$counter");
fclose($fp);
$fp = fopen ($file, "r");
$count = fgets($fp);
echo $count;
?>

I tried this:

$fp = fopen ($file, "r+");
fwrite ($fp, "$counter");
$count = fgets($fp);
echo $count;

But $count returned an empty string (or would not echo).



Andy Hassall
Guest
 
Posts: n/a
#2: Jul 17 '05

re: Reading from file basics


On Thu, 18 Mar 2004 22:28:42 GMT, "deko" <dje422@hotmail.com> wrote:
[color=blue]
>Is there a way to avoid opening and closing the file "viscount" twice in this
>code:
>
><?php
>$file = 'viscount.txt';
>if ($counter = @file ($file)) {
> $line = each($counter);
> if (!$counter) {
> $counter = 1;
> } else {
> $counter = $line[value]+1;
> }
>}
>$fp = fopen ($file, "w");
>fwrite ($fp, "$counter");
>fclose($fp);
>$fp = fopen ($file, "r");
>$count = fgets($fp);
>echo $count;
>?>
>
>I tried this:
>
>$fp = fopen ($file, "r+");
>fwrite ($fp, "$counter");
>$count = fgets($fp);
>echo $count;
>
>But $count returned an empty string (or would not echo).[/color]

Looks like you're assuming vicount contains a single line with a counter on
it? You're missing file locking here - what if two people run the script at the
same time? This is the sort of thing databases were invented for.

Having said that, if you either put flock() calls in, or ignore the race
condition, why are you re-opening the file and reading what you just wrote -
just echo $counter back out?

--
Andy Hassall <andy@andyh.co.uk> / Space: disk usage analysis tool
<http://www.andyh.co.uk> / <http://www.andyhsoftware.co.uk/space>
Pedro Graca
Guest
 
Posts: n/a
#3: Jul 17 '05

re: Reading from file basics


deko wrote:[color=blue]
> Is there a way to avoid opening and closing the file "viscount" twice in this
> code:[/color]

Yes

<?php
// open file for reading and writing
if (!$fh = @fopen('viscount', 'r+')) exit('fopen failed');

// lock it, try ten times before giving up
$lock_tries = 10;
while (!flock($fh, LOCK_EX)) {
usleep(100);
--$lock_tries;
if (!$lock_tries) break;
}
if (!$lock_tries) exit('flock (to lock) failed');

// read data
if (!$line = @fgets($fh)) exit('fgets failed');

// do whatever you want with the data (... but do it fast)
$line = (int)(trim($line));
++$line;

// go to beginning of file
if (@fseek($fh, 0)) exit('fseek failed');

// clear all data in file (maybe not needed ???)
if (!ftruncate($fh, 0)) exit('ftruncate failed');

// write new data
if (!fwrite($fh, $line . "\n")) exit('fwrite failed');

// unlock file, try ten times before giving up
$lock_tries = 10;
while (!flock($fh, LOCK_UN)) {
usleep(100);
--$lock_tries;
if (!$lock_tries) break;
}
if (!$lock_tries) exit('flock (to unlock) failed');

// close file
if (!fclose($fh)) exit('fclose failed');

// file updated, let the user know about it
exit('File updated, thank you for using our service.');
?>

--
USENET would be a better place if everybody read: : mail address :
http://www.catb.org/~esr/faqs/smart-questions.html : is valid for :
http://www.netmeister.org/news/learn2quote2.html : "text/plain" :
http://www.expita.com/nomime.html : to 10K bytes :
deko
Guest
 
Posts: n/a
#4: Jul 17 '05

re: Reading from file basics


> Looks like you're assuming visount contains a single line with a counter on[color=blue]
> it? You're missing file locking here - what if two people run the script at[/color]
the[color=blue]
> same time? This is the sort of thing databases were invented for.[/color]

I agree, a database could be used - but this is a traffic counter, and that
would mean a lot of overhead if I were using a database.
[color=blue]
> Having said that, if you either put flock() calls in, or ignore the race
> condition, why are you re-opening the file and reading what you just wrote -
> just echo $counter back out?[/color]

How do I ignore the race condition? would that be better than using flock()?

<?php
$file = 'viscount.txt';
if ($counter = @file ($file)) {
$line = each($counter);
if (!$counter) {
$counter = 1;
} else {
$counter = $line[value]+1;
}
}
$fp = fopen ($file, "w");
fwrite ($fp, "$counter");
fclose($fp);
$fp = fopen ($file, "r");
$count = fgets($fp);
echo $count;
?>





Andy Hassall
Guest
 
Posts: n/a
#5: Jul 17 '05

re: Reading from file basics


On Fri, 19 Mar 2004 22:31:48 GMT, "deko" <dje422@hotmail.com> wrote:
[color=blue][color=green]
>> Looks like you're assuming visount contains a single line with a counter on
>> it? You're missing file locking here - what if two people run the script at
>> the same time? This is the sort of thing databases were invented for.[/color]
>
>I agree, a database could be used - but this is a traffic counter, and that
>would mean a lot of overhead if I were using a database.
>[color=green]
>> Having said that, if you either put flock() calls in, or ignore the race
>> condition, why are you re-opening the file and reading what you just wrote -
>> just echo $counter back out?[/color]
>
>How do I ignore the race condition?[/color]

The problem is you already are :-)
[color=blue]
>would that be better than using flock()?[/color]

No. See Pedro Graca's post.

--
Andy Hassall <andy@andyh.co.uk> / Space: disk usage analysis tool
<http://www.andyh.co.uk> / <http://www.andyhsoftware.co.uk/space>
Closed Thread