Непосредственная модификация файла без временной копии

Задача
Необходимо изменить файл, не создавая временный файл для сохранения изменений.

Решение
Прочитайте файл в память, выполните изменения и перезапишите файл. Откройте файл в режиме r+ (в Windows rb+, если необходимо) и откорректируйте его длину с помощью функции ftruncate() после записи изменений:

// открываем файл на чтение и запись
$fh = fopen('pickles.txt','r+') or die($php_errormsg);
// читаем весь файл в переменную $s
$s = fread($fh,filesize('pickles.txt')) or die($php_errormsg);
// ... модифицируем $s ...
// ищем начало файла и записываем новую переменную $s
rewind($fh);
if (-1 == fwrite($fh,$s)) { die($php_errormsg); }
// подгоняем длину файла к тому, что было записано
ftruncate($fh,ftell($fh)) or die($php_errormsg);
// закрываем файл
fclose($fh) or die($php_errormsg);

Обсуждение
Следующая программа превращает текст, выделенный звездочками или косыми чертами, в текст с тегами HTML или :

$fh = fopen('message.txt','r+') or die($php_errormsg);
// читаем весь файл в переменную $s
$s = fread($fh,filesize('message.txt')) or die($php_errormsg);
// преобразуем *word* to word
$s = preg_replace('@\*(.*?)\*@i','$1',$s);
// преобразуем /word/ to word
$s = preg_replace('@/(.*?)/@i','$1',$s);
rewind($fh);
if (-1 == fwrite($fh,$s)) { die($php_errormsg); }
ftruncate($fh,ftell($fh)) or die($php_errormsg);
fclose($fh) or die($php_errormsg);

Поскольку добавление тегов HTML приводит к росту файла, то весь файл должен быть прочитан в память, а затем обработан.


Если измене-ния в файле уменьшают длину каждой строки (или оставляют тот же размер), то файл можно обработать строку за строкой, сэкономив память. Следующий пример преобразует текст, размеченный тегами
и , в текст, выделенный звездочками и косыми чертами:

$fh = fopen('message.txt','r+') or die($php_errormsg);
// определяем количество байт для чтения
$bytes_to_read = filesize('message.txt');
// инициализируем переменные, хранящие позиции в файле
$next_read = $last_write = 0;
// продолжаем, пока есть байты для чтения
while ($next_read < $bytes_to_read) {
/* переходим в следующую позицию чтения, читаем строку и сохраняем
* позицию для следующего чтения */
fseek($fh,$next_read);
$s = fgets($fh,1048576) or die($php_errormsg);
$next_read = ftell($fh);
// преобразуем word в *word*
$s = preg_replace('@]*>(.*?)
@i','*$1*',$s);
// преобразуем word в /word/
$s = preg_replace('@]*>(.*?)
@i','/$1/',$s);
/* переходим в позицию, где закончилась предыдущая запись, записываем
* преобразованную строку и сохраняем позицию для следующей записи */
fseek($fh,$last_write);
if (-1 == fwrite($fh,$s)) { die($php_errormsg); }
$last_write = ftell($fh);
}
// сокращаем длину файла до величины прочитанного
ftruncate($fh,$last_write) or die($php_errormsg);
// закрываем файл
fclose($fh) or die($php_errormsg);.



Оцените статью: (0 голосов)
0 5 0

Статьи из раздела PHP на эту тему:
Блокировка файла
Выбор случайной строки из файла
Запись в несколько файловых дескрипторов одновременно
Запись в стандартный поток вывода
Обработка каждого слова в файле

Вернуться в раздел: PHP / 18. Файлы