thelolcat
thelolcat

Reputation: 11645

How to rewrite same file

Currently I'm doing it like this:

$f = fopen('test', 'w');
fwrite($f, 'Hi');
fclose($f);

But I have a loop that does some expensive stuff (with files), and I'd like to avoid opening and closing the file handle every time I want to overwrite "test"

It should be something like this:

$f = fopen('test', 'w');

$i = 0;
while($ < 50000){

  $i++;
  foverwrite($f, 'i = ' . $i);

  sleep(5); // just a example

}

fclose($f);

Is this possible?

This script runs in the background in CLI mode and I'm reading the test file from the web with ajax like every 2 seconds. Basically I'm trying to display a progress bar lol

Upvotes: 12

Views: 825

Answers (5)

geomagas
geomagas

Reputation: 3280

To go along with your example, you could implement your foverwrite() function using frewind() like this:

function foverwrite($handle,$content)
  {
  frewind($handle);
  return fwrite($handle,$content);
  }

This function will return fwrite()'s return value, so it can readily replace fwrite() where needed. Also, in case of opening the file in append mode (a or a+) it will just append contens, as frewind() will make no difference.

However, concerning the purpose of your script, which clearly is interprocess communication, you should take a look at more efficient techniques, like shared memory.

Upvotes: 2

Shushant
Shushant

Reputation: 1635

You can do it in following ways

$data = [];//initiate the $data variable as empty array
$i = 0;
while($i < 50000){

  $data[] = 'i = ' . $i;
  $i++;
}
file_put_contents('file.txt', implode("\n", $data));// implode the array

Upvotes: 1

r3mainer
r3mainer

Reputation: 24587

If you're just aiming to keep a file updated so that it can be accessed by AJAX requests, then do you really need to update it 50000 times? A simple way of cutting your overhead would be to update the file less often. Like this, for example:

for ($i=0; $i<50000; $i++) {

  // update progress file every 1000 iterations:
  if (!($i % 1000)) file_put_contents('./file.txt', "i = $i");

  // --- do stuff ---

}
file_put_contents($f, "i = 50000");

Upvotes: 1

William Entriken
William Entriken

Reputation: 39333

You can keep the file and just rewrite over the contents, while then truncating the file if the size changed. This will be faster than overwriting or deleting and rewriting.

$f = fopen('test', 'w');
$i = 0;
while($i < 50000){
  $i++;

  rewind($f);
  $data = 'i = ' . $i;
  fwrite($f, $data);
  ftruncate($f, strlen($data)); // <---------- Here's the ticket

  sleep(5);
}

fclose($f);

Upvotes: 8

ern0
ern0

Reputation: 3172

You can update the content of a file by rewinding the file pointer, see fseek(). Be careful, once you set file lenght to N by writing N bytes to it, next time, if you rewind and write X < N bytes, the file will remain N bytes long, containing X bytes of new data and N-X bytes of old stuff.

Anyway, don't worry about opening and closing files several times, they will be cached. Or you can open it on a ramdisk partition.

Upvotes: 9

Related Questions