ftruncate()
Функция ftruncate() в PHP усекает открытый файл до указанного числа байт. Синтаксис, примеры и типичные случаи использования.
Функция ftruncate() в PHP изменяет размер открытого файла до точного числа байт. Она может как уменьшить файл (отрезав всё, что идёт после заданной длины), так и увеличить его (дополнив новое пространство нулевыми байтами). На этой странице описаны синтаксис, возвращаемое значение, правила работы с указателем файла и типичные практические сценарии — очистка лога, исправление повреждённой записи или предварительное выделение места, — а также приведены запускаемые примеры.
Что делает функция ftruncate()
ftruncate() усекает открытый файл до длины, которую вы задаёте, измеряемой в байтах:
- Если файл больше, чем
length, лишние байты отбрасываются. - Если файл меньше, чем
length, он расширяется, а новая область заполняется нулевыми байтами (\0). - Если
lengthравно0, файл очищается — это обычный способ обнулить файл без его удаления.
Функция возвращает true в случае успеха и false в случае ошибки. Важно: ftruncate() не перемещает внутренний указатель файла. Если вы записали данные до байта 50, а затем усекли файл до 10 байт, указатель по-прежнему будет на позиции 50, поэтому следующая запись начнётся оттуда и снова расширит файл нулевыми байтами. Используйте rewind() или fseek(), чтобы сбросить указатель после усечения.
Синтаксис
ftruncate(resource $stream, int $size): bool$stream— указатель на файл, возвращённый функциейfopen(). Файл должен быть открыт в режиме записи (r+,w,w+,a+и т. д.). Открытие с флагомr(только для чтения) приведёт к тому, чтоftruncate()завершится ошибкой.$size— новый размер файла в байтах (неотрицательное целое число).
Как использовать ftruncate()
Схема всегда состоит из трёх одинаковых шагов:
- Открыть файл в режиме записи с помощью
fopen(). - Вызвать
ftruncate(), передав указатель на файл и целевой размер. - Закрыть файл с помощью
fclose().
Пример ниже записывает известную строку, усекает её до 5 байт и считывает результат обратно, чтобы было видно, что именно сохранилось:
<?php
$filename = 'demo.txt';
// Open for reading and writing; create if it does not exist.
$file = fopen($filename, 'w+');
fwrite($file, 'Hello, World!'); // 13 bytes
ftruncate($file, 5); // keep only the first 5 bytes
rewind($file); // pointer was at 13 — move it back to 0
echo fread($file, 1024); // Hello
fclose($file);Результат выполнения:
HelloОстаётся только Hello, потому что файл был обрезан до 5 байт. Обратите внимание на вызов rewind() — без него fread() начнёт чтение с байта 13 (за концом файла) и вернёт пустую строку.
Расширение файла нулевыми байтами
Когда $size превышает текущий размер файла, ftruncate() расширяет его, заполняя новую область символами \0. Это удобно для предварительного выделения файла фиксированного размера:
<?php
$file = fopen('padded.txt', 'w+');
fwrite($file, 'abc'); // 3 bytes
ftruncate($file, 8); // grow to 8 bytes; 5 null bytes added
clearstatcache(); // discard any cached stat info
echo filesize('padded.txt') . " bytes\n";
fclose($file);Результат выполнения:
8 bytesТеперь файл занимает 8 байт — исходные abc плюс пять нулевых (\0) байт. Вызов clearstatcache() важен, потому что PHP кэширует результаты функций на основе stat, таких как filesize(), в пределах одного запроса; если вы уже читали размер файла раньше, кэшированное значение может устареть после усечения.
Типичные сценарии использования
- Очистка файла на месте.
ftruncate($file, 0)очищает лог или файл кэша, сохраняя его inode, права доступа и любые открытые дескрипторы. Это безопаснее, чем удалять и воссоздавать файл. - Удаление последней записи. Прочитайте файл, найдите начало последней записи и усеките файл до этого смещения, чтобы удалить её без перезаписи всего файла.
- Исправление частично записанного файла. Если запись была прервана, усечение до заведомо корректной длины восстанавливает рабочее состояние.
- Предварительное выделение места. Зарезервируйте файл фиксированного размера заранее (например, бинарный индекс) перед заполнением данными.
Подводные камни
- Дескрипторы только для чтения завершаются ошибкой. Открытие с флагом
rи вызовftruncate()вернутfalseи вызовут предупреждение. Используйтеr+, если нужно сохранить существующее содержимое, но при этом иметь возможность записи. - Указатель не перемещается. Всегда вызывайте
rewind()илиfseek()перед чтением или дозаписью после усечения, иначе вы можете создать неожиданное заполнение нулевыми байтами. - Устаревший кэш stat. Функции
filesize()и им подобные могут возвращать старый размер сразу после усечения; вызовитеclearstatcache(), чтобы получить актуальное значение. lengthзадаётся в байтах, а не в символах. При работе с многобайтовым (UTF-8) текстом усечение в середине символа может повредить последний символ.
Связанные функции
fopen()— открыть файл перед усечением.fwrite()— записать данные в файл.fread()— прочитать содержимое файла.fseek()/rewind()— переместить указатель после усечения.fclose()— закрыть файл по завершении работы.
Заключение
ftruncate() — точный инструмент для изменения размера открытого файла в PHP: уменьшение достигается отсечением хвостовых байт, увеличение — заполнением нулевыми байтами. Главное, что нужно помнить: файл должен быть открыт в режиме записи, функция никогда не перемещает указатель файла, а для получения актуального размера может потребоваться вызов clearstatcache(). В связке с fopen(), fwrite() и fclose() она решает задачи от очистки логов до восстановления частично записанных файлов.