@ Ответ codaddict вполне достаточен для небольших файлов (и я хотел бы реализовать его, если бы размер файла был ниже MiB).Однако он израсходует кучу памяти, и поэтому вам следует быть осторожным при чтении больших файлов.
Если вы хотите гораздо более дружественную к памяти версию, вы можете использовать потоковые фильтры ...
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');
Итак, вы можете добавить фильтр произвольного потока.Имя фильтра определяет аргументы:
$search = 'foo';
$replace = 'bar';
$name = 'replacetext.'.$search.'|'.$replace;
stream_filter_append($stream, $name);
или для массивов:
$search = array('foo', 'bar');
$replace = array('bar', 'baz');
$name = 'replacetext.'.implode(',', $search).'|'.implode(',', $replace);
stream_filter_append($stream, $name);
Очевидно, что это действительно простой пример (и он не выполняет много ошибок), ноэто позволяет вам делать что-то вроде этого:
$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');
И это будет поддерживать очень низкое использование памяти при обработке потенциально огромных (GiB или TiB) файлов ...
Да, и другиеклассная вещь, это может встроенное редактирование различных типов потоков.Я имею в виду, что вы можете читать из HTTP-потока, редактировать inline и записывать в файловый поток.Он довольно мощный (как вы можете связать эти фильтры) ...