Recipe 23.12. Modifying a File in Place Without a Temporary File


23.12.1. Problem

You want to change a file without using a temporary file to hold the changes.

23.12.2. Solution

Read the file with file_get_contents( ), make the changes, and rewrite the file with file_put_contents( ). This is shown in Example 23-32.

Changing a file in place

<?php $contents = file_get_contents('pickles.txt'); $contents = strtoupper($contents); file_put_contents('pickles.txt', $contents); ?>

23.12.3. Discussion

Example 23-33 turns text emphasized with asterisks or slashes into text with HTML <b> or <i> tags.

HTML-ifying a file in place

<?php $contents = file_get_contents('message.txt'); // convert *word* to <b>word</b> $contents = preg_replace('@\*(.*?)\*@i','<b>$1</b>',$contents); // convert /word/ to <i>word</i> $contents = preg_replace('@/(.*?)/@i','<i>$1</i>',$contents); file_put_contents('message.txt', $contents); 

Because adding HTML tags makes the file grow, the entire file has to be read into memory and then processed. If the changes to a file make each line shrink (or stay the same size), the file can be processed line by line, saving memory. Example 23-34 converts text marked with <b> and <i> to text marked with asterisks and slashes.

Text-ifying a file in place

<?php $fh = fopen('message.txt','r+')         or die($php_errormsg); // figure out how many bytes to read $bytes_to_read = filesize('message.txt'); // initialize variables that hold file positions $next_read = $last_write = 0; // keep going while there are still bytes to read while ($next_read < $bytes_to_read) {     /* move to the position of the next read, read a line, and save      * the position of the next read */     fseek($fh,$next_read);     $s = fgets($fh)                     or die($php_errormsg);     $next_read = ftell($fh);     // convert <b>word</b> to *word*     $s = preg_replace('@<b[^>]*>(.*?)</b>@i','*$1*',$s);     // convert <i>word</i> to /word/     $s = preg_replace('@<i[^>]*>(.*?)</i>@i','/$1/',$s);     /* move to the position where the last write ended, write the      * converted line, and save the position for the next write */     fseek($fh,$last_write);     if (-1 == fwrite($fh,$s))            { die($php_errormsg); }     $last_write = ftell($fh); } // truncate the file length to what we've already written ftruncate($fh,$last_write)              or die($php_errormsg); // close the file fclose($fh)                             or die($php_errormsg);

23.12.4. See Also

Recipes 13.12 and 13.13 for additional information on converting between plain text and HTML; documentation on fseek( ) at http://www.php.net/fseek, rewind( ) at http://www.php.net/rewind, ftruncate( ) at http://www.php.net/ftruncate, file_get_contents( ) at http://www.php.net/file_get_contents, and file_put_contents( ) at http://www.php.net/file_put_contents.




PHP Cookbook, 2nd Edition
PHP Cookbook: Solutions and Examples for PHP Programmers
ISBN: 0596101015
EAN: 2147483647
Year: 2006
Pages: 445

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net