Fflush: примеры (PHP)

Полный обзор PHP функции fflush для работы с буфером
Раздел: Работа с файлами
fflush(resource $stream): bool
Описание функции fflush в PHP

Функция fflush принудительно записывает (сбрасывает) в файл все буферизованные данные, которые еще не были записаны для заданного файлового указателя.

Когда используется

Функция необходима для принудительной синхронизации содержимого буфера с физическим файлом на диске. Это важно, когда требуется немедленная запись данных без ожидания заполнения буфера или закрытия файла. Часто применяется в логгерах, демонах, сценариях реального времени и при работе с критически важными данными, где потеря информации недопустима.

Аргументы функции

Функция принимает один обязательный аргумент:

  • $stream (resource) - Файловый указатель (resource), полученный с помощью функции fopen() или fsockopen(). Указатель должен быть открыт для записи.
Простые примеры использования fflush
Пример 1: Базовое использование с файлом

Запись строки и принудительный сброс буфера.

$fp = fopen('log.txt', 'a');
fwrite($fp, "Новая запись\n");
$result = fflush($fp);
var_dump($result);
fclose($fp);
bool(true)
Пример 2: Сравнение с работой без fflush

Демонстрация поведения при неожиданном завершении скрипта.

// Без 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

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('Буфер сброшен')
JavaScript (Node.js)

Метод 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).

Типичные ошибки и их причины
Ошибка 1: Передача невалидного ресурса

Функция ожидает корректный файловый указатель, открытый для записи.

$fp = false;
$result = fflush($fp); // Не ресурс
var_dump($result);
Warning: fflush() expects parameter 1 to be resource, bool given
NULL
Ошибка 2: Попытка сброса буфера потока, открытого только для чтения
$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)
Ошибка 3: Сброс буфера закрытого файлового указателя
$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) даже если нечего было сбрасывать
Расширенные примеры применения
Пример 1: Мониторинг лог-файла в реальном времени

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

Пример php
// 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);
Пример 2: Синхронизация данных между процессами

Запись в один файл из нескольких параллельных процессов.

Пример php
// 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);
Пример 3: Работа с сокетами

fflush можно использовать с сокетами, открытыми через fsockopen, для немедленной отправки данных.

Пример php
$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);
}
Пример 4: Комбинирование с пользовательской буферизацией вывода

Использование в связке с ob_start для контроля над выводом в браузер.

Пример php
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);

PHP fflush function comments

En
Fflush Flushes the output to a file