ftell()
Функция ftell() в PHP возвращает текущую позицию указателя файла — байтовое смещение от начала файла.
Что такое функция ftell()?
Функция ftell() — встроенная функция PHP, которая возвращает текущую позицию файлового указателя — байтовое смещение от начала файла, на котором произойдёт следующая операция чтения или записи. Каждый открытый дескриптор файла хранит внутренний курсор; функции fread(), fwrite() и fgets() продвигают его вперёд, а fseek() и rewind() перемещают его явно. ftell() просто сообщает, где находится этот курсор в данный момент, не изменяя его.
Знание смещения полезно, когда нужно запомнить текущее положение в файле (чтобы потом вернуться к нему с помощью fseek()), подсчитать количество прочитанных байт или обнаружить конец записи в файле с фиксированной шириной записи или в двоичном файле.
На этой странице рассматриваются синтаксис, готовый к запуску пример, возвращаемые значения ftell(), распространённые подводные камни (режим дозаписи, потоки), а также связь с другими функциями управления файловым указателем.
Синтаксис
ftell(resource $stream): int|false$stream должен быть файловым указателем, возвращённым функцией fopen() (или такой функцией, как fsockopen()). Функция возвращает позицию в виде целочисленного байтового смещения или false в случае ошибки — например, если поток не поддерживает позиционирование. Поскольку 0 (начало файла) является допустимым «ложным» результатом, всегда проверяйте возвращаемое значение с помощью ===:
$pos = ftell($file);
if ($pos === false) {
// could not determine the position
}Как использовать функцию ftell()
Типичный порядок действий:
- Откройте файл с помощью
fopen()в нужном режиме. - Прочитайте данные из файла или запишите их, чтобы указатель переместился.
- Вызовите
ftell()с файловым указателем, чтобы узнать его позицию. - Используйте полученное смещение — например, сохраните его или передайте в
fseek(). - Закройте файл с помощью
fclose().
Приведённый ниже пример полностью самодостаточен: он сначала создаёт временный файл, поэтому вы можете запустить его без предварительной подготовки данных.
<?php
// Create a temporary file with known contents.
$filename = tempnam(sys_get_temp_dir(), 'demo');
file_put_contents($filename, 'Hello, World! This is a test.');
$file = fopen($filename, 'r');
echo "Start position: " . ftell($file) . "\n"; // 0
fread($file, 5); // read "Hello"
echo "After reading 5 bytes: " . ftell($file) . "\n"; // 5
fread($file, 5); // read ", Wor"
echo "After reading 5 more: " . ftell($file) . "\n"; // 10
rewind($file); // jump back to the start
echo "After rewind: " . ftell($file) . "\n"; // 0
fseek($file, 7); // jump to byte 7
echo "After fseek to 7: " . ftell($file) . "\n"; // 7
echo "Next 5 bytes: " . fread($file, 5) . "\n"; // "World"
fclose($file);
unlink($filename);Вывод:
Start position: 0
After reading 5 bytes: 5
After reading 5 more: 10
After rewind: 0
After fseek to 7: 7
Next 5 bytes: WorldКаждый вызов fread() смещает указатель на количество фактически прочитанных байт, поэтому ftell() возвращает последовательно 0, 5, затем 10. rewind() сбрасывает указатель в 0, а fseek($file, 7) перемещает его прямо к байту 7, с которого начинается слово World.
Режим дозаписи: распространённый подводный камень
Когда файл открыт в режиме дозаписи ('a' или 'a+'), каждая запись всегда выполняется в конец файла, независимо от текущей позиции указателя. Сразу после открытия ftell() может вернуть 0, хотя записи будут добавляться в конец — его возвращаемое значение в режиме дозаписи не отражает достоверно позицию следующей записи. Если нужны точные позиции, открывайте файл с 'r+', 'w+' или 'c+' и явно перемещайте указатель.
Аналогичная ситуация с непозиционируемыми потоками (например, некоторыми сетевыми потоками или каналами): они не могут сообщить осмысленную позицию, и ftell() возвращает для них false.
Связанные функции
ftell() редко используется в одиночку. Она входит в небольшое семейство функций управления файловым указателем:
fopen()— открыть файл и получить указатель, который читаетftell().fread()— читать байты и продвигать указатель.fwrite()— записывать байты и продвигать указатель.fseek()— перемещать указатель на абсолютную или относительную позицию; используйте в паре сftell()для сохранения и восстановления смещений.rewind()— сбросить указатель в начало (эквивалентноfseek($file, 0)).fclose()— закрыть файл по завершении работы.
Для общего обзора см. Работа с файлами в PHP.
Заключение
Функция ftell() возвращает текущее байтовое смещение файлового указателя, не изменяя его, что делает её естественным дополнением к fseek() и rewind() при навигации по файлам. Не забывайте сравнивать результат с === false (поскольку 0 — допустимое смещение) и помните, что режим дозаписи и непозиционируемые потоки не обеспечивают надёжного возврата позиции.