开发者

Replacing file content in PHP

I need a function just like preg_re开发者_C百科place but instead of strings I need it to work with files / file content.


You can do:

$file = 'filename';
file_put_contents($file,str_replace('find','replace',file_get_contents($file)));


@codaddict's answer is quite sufficent for small files (and would be how I would implement it if the size of the file was under a MiB). However it will eat up a ton of memory, and as such you should be careful when reading large files.

If you want a much more memory friendly version, you could use stream filters...

class ReplaceText_filter extends php_user_filter {
    protected $search = '';
    protected $replace = '';

    public function filter($in, $out, &$consumed, $closing) {
        while ($bucket = stream_bucket_make_writable($in)) {
            $bucket->data = str_replace(
                $this->search, 
                $this->replace, 
                $bucket->data
            );
            $consumed += $bucket->datalen;
            stream_bucket_append($out, $bucket);
        }
        return PSFS_PASS_ON;
    }

    public function onCreate() {
        if (strpos($this->filtername, '.') === false) return false;
        list ($name, $arguments) = explode('.', $this->filtername, 2);
        $replace = '';
        $search = $arguments;
        if (strpos($arguments, '|') !== false) {
            list ($search, $replace) = explode('|', $arguments, 2);
        }
        if (strpos($search, ',') !== false) {
            $search = explode(',', $search);
        }
        if (strpos($replace, ',') !== false) {
            $search = explode(',', $replace);
        }
        $this->search = $search;
        $this->replace = $replace;
    }
}
stream_filter_register('replacetext.*', 'ReplaceText_Filter');

So, then you can append an arbitrary stream filter. The filter's name determines the arguments:

$search = 'foo';
$replace = 'bar';
$name = 'replacetext.'.$search.'|'.$replace;
stream_filter_append($stream, $name);

or for arrays,

$search = array('foo', 'bar');
$replace = array('bar', 'baz');
$name = 'replacetext.'.implode(',', $search).'|'.implode(',', $replace);
stream_filter_append($stream, $name);

Obviously this is a really simple example (and doesn't do a lot of error checking), but it allows you to do something like this:

$f1 = fopen('mysourcefile', 'r');
$f2 = fopen('mytmpfile', 'w');
$search = array('foo', 'bar');
$replace = array('bar', 'baz');
$name = 'replacetext.'.implode(',', $search).'|'.implode(',', $replace);
stream_filter_append($f1, $name);
stream_copy_to_stream($f1, $f2);
fclose($f1);
fclose($f2);
rename('mytmpfile', 'mysourcefile');

And that will keep memory usage very low while processing potentially huge (GiB or TiB) files...

Oh, and the other cool thing, is it can inline edit differing stream types. What I mean by that is that you can read from a HTTP stream, edit inline, and write to a file stream. It's quite powerful (as you can chain these filters)...


<?php

$pattern = "/created/";
$replacement = "XXXXX";
$file_name = "regex.txt";
$getting_file_contents = file_get_contents($file_name);

echo("Original file contents : " . "<br><br>");
var_dump($getting_file_contents);
echo("<br><br><br>");

if ($getting_file_contents == true) {
  echo($file_name . " had been read succesfully" . "<br><br><br>");

  $replace_data_in_file = preg_replace($pattern, $replacement, $getting_file_contents);
  $writing_replaced_data = file_put_contents($file_name, $replace_data_in_file);
  echo("New file contents : " . "<br><br>");
  var_dump($replace_data_in_file);
  echo("<br><br>");

  if ($writing_replaced_data == true) {
    echo("Data in the file changed");
  }
  else {
    exit("Cannot change data in the file");
  }
}
else {
  exit("Unable to get file contents!");
}

?>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜