Fflush: примеры (PHP)
fflush(resource $stream): boolФункция fflush принудительно записывает (сбрасывает) в файл все буферизованные данные, которые еще не были записаны для заданного файлового указателя.
Функция необходима для принудительной синхронизации содержимого буфера с физическим файлом на диске. Это важно, когда требуется немедленная запись данных без ожидания заполнения буфера или закрытия файла. Часто применяется в логгерах, демонах, сценариях реального времени и при работе с критически важными данными, где потеря информации недопустима.
Функция принимает один обязательный аргумент:
- $stream (resource) - Файловый указатель (resource), полученный с помощью функции fopen() или fsockopen(). Указатель должен быть открыт для записи.
Запись строки и принудительный сброс буфера.
$fp = fopen('log.txt', 'a');
fwrite($fp, "Новая запись\n");
$result = fflush($fp);
var_dump($result);
fclose($fp);bool(true)
Демонстрация поведения при неожиданном завершении скрипта.
// Без fflush - данные могут быть потеряны
$fp = fopen('test1.txt', 'w');
fwrite($fp, "Эти данные в буфере");
// Симуляция фатальной ошибки или прерывания
// В файле test1.txt может быть пусто
// С использованием fflush
$fp2 = fopen('test2.txt', 'w');
fwrite($fp2, "Эти данные сброшены на диск\n");
fflush($fp2); // Данные записываются немедленно
// Даже если скрипт прекратится, данные в файле останутся.
fclose($fp);
fclose($fp2);PHP предлагает несколько функций для управления выводом и буферизацией.
- flush() - Сбрасывает системные буферы вывода PHP. Не работает с файловыми указателями, а с буфером вывода веб-сервера. Эффект зависит от конфигурации сервера.
- ob_flush() - Сбрасывает (отправляет) содержимое буфера вывода. Работает с буферами, созданными ob_start(). Используется для инкрементальной отправки данных клиенту в веб-приложениях.
- file_put_contents() - Запись данных в файл. Эта функция внутренне открывает файл, записывает данные и закрывает его, что автоматически вызывает сброс буфера. Удобна для атомарных операций записи, но менее эффективна при множественных записях в один файл по сравнению с fopen() + fwrite() + fflush().
Выбор функции: fflush() применяется для низкоуровневой работы с открытыми файловыми потоками (resource). ob_flush() и flush() предназначены для управления выводом в веб-браузер. file_put_contents() подходит для простых однократных записей.
Fflush в Python
Метод flush() файлового объекта. В отличие от PHP, в Python файлы часто буферизуются построчно.
with open('log.txt', 'a') as f:
f.write('Новая запись\n')
f.flush() # Немедленная запись на диск
print('Буфер сброшен')Метод filehandle.sync() (или fs.fsync()) для синхронизации. Node.js также использует буферизацию.
const fs = require('fs/promises');
async function example() {
const filehandle = await fs.open('log.txt', 'a');
await filehandle.write('Новая запись\n');
await filehandle.sync(); // Аналог fflush + fsync
await filehandle.close();
}Fflush в C
Функция fflush() из стандартной библиотеки. Поведение практически идентично PHP.
FILE *fp = fopen("log.txt", "a");
fprintf(fp, "Новая запись\n");
fflush(fp); // Сброс буфера
fclose(fp);Отличие PHP 8: Функция в PHP работает только с файловыми потоками, в то время как в C она также может сбрасывать буфер стандартного вывода (stdout).
Функция ожидает корректный файловый указатель, открытый для записи.
$fp = false;
$result = fflush($fp); // Не ресурс
var_dump($result);Warning: fflush() expects parameter 1 to be resource, bool given
NULL
$fp = fopen('log.txt', 'r');
$result = fflush($fp);
var_dump($result);
fclose($fp);Warning: fflush(): supplied resource is not a valid stream resource
bool(false)
$fp = fopen('log.txt', 'a');
fclose($fp);
$result = fflush($fp);
var_dump($result);Warning: fflush(): supplied resource is not a valid stream resource
bool(false)
Для избежания ошибок важно проверять успешность открытия файла и режим доступа.
- PHP 8.0.0: Тип возвращаемого значения функции fflush() изменен с int на bool. Ранее функция возвращала 1 (true) в случае успеха, теперь возвращает true. В случае неудачи ранее возвращался 0, теперь возвращается false. Это изменение является частью общей инициативы по стандартизации типов возвращаемых значений в ядре PHP.
- До версии PHP 8.0.0 функция могла возвращать 0 для успешного сброса буфера в некоторых средах, где операция считалась "пустой" (нечего было сбрасывать). С версии 8.0.0 в таких случаях функция возвращает true.
// Поведение до PHP 8.0
$fp = fopen('log.txt', 'a');
$result = fflush($fp);
var_dump($result); // Могло вывести int(1) или int(0) при "пустом" сбросе
// Поведение в PHP 8.0 и новее
$fp = fopen('log.txt', 'a');
$result = fflush($fp);
var_dump($result); // Выводит bool(true) даже если нечего было сбрасыватьИспользование fflush для немедленного отображения записей в логе, который читается другим процессом.
// writer.php - процесс, который пишет логи
$logFile = fopen('application.log', 'a');
stream_set_blocking($logFile, false); // Неблокирующий режим (опционально)
for ($i = 0; $i < 5; $i++) {
$message = date('H:i:s') . " Event $i\n";
fwrite($logFile, $message);
fflush($logFile); // Немедленная запись, чтобы читатель увидел
sleep(1); // Пауза между событиями
}
fclose($logFile);Запись в один файл из нескольких параллельных процессов.
// worker.php
$fp = fopen('shared_counter.txt', 'c+'); // 'c+' для создания и чтения/записи
// Блокировка файла для избежания гонок
if (flock($fp, LOCK_EX)) {
$count = (int) fread($fp, 1024);
rewind($fp); // Возврат указателя в начало
$count++;
ftruncate($fp, 0); // Очистка файла
fwrite($fp, (string) $count);
fflush($fp); // Важно: сброс до снятия блокировки!
flock($fp, LOCK_UN); // Снятие блокировки
}
fclose($fp);fflush можно использовать с сокетами, открытыми через fsockopen, для немедленной отправки данных.
$socket = fsockopen('tcp://example.com', 80, $errno, $errstr, 30);
if ($socket) {
$request = "GET / HTTP/1.1\r\n";
$request .= "Host: example.com\r\n";
$request .= "Connection: close\r\n\r\n";
fwrite($socket, $request);
fflush($socket); // Принудительная отправка запроса
while (!feof($socket)) {
echo fgets($socket, 128);
}
fclose($socket);
}Использование в связке с ob_start для контроля над выводом в браузер.
ob_start(); // Включение буферизации вывода
echo "Начало контента. ";
$fp = fopen('log.txt', 'a');
fwrite($fp, "Запись 1\n");
fflush($fp); // Сброс буфера файла, но не буфера вывода
sleep(2); // Долгая операция
echo "Конец контента.";
// Сброс буфера вывода в браузер
ob_flush();
flush();
fwrite($fp, "Запись 2 после отправки контента\n");
fclose($fp);