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

Использование fputs для записи данных в файлы на PHP
Раздел: Работа с файлами
fputs(resource $stream, string $data, ?int $length = null): int|false

Функция fputs в PHP

Назначение и описание

Функция fputs() является псевдонимом (alias) для функции fwrite(). Она применяется для записи строковых данных в файл, используя предварительно открытый файловый дескриптор (ресурс). Основное применение – бинарно-безопасная запись в файлы, сокеты или другие потоки ввода-вывода.

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

Функция принимает три аргумента:

  • $stream (resource): Обязательный. Файловый указатель (ресурс), который должен быть корректным и открытым для записи (например, с помощью fopen() с режимом 'w', 'a', 'c', 'x' или 'r+').
  • $data (string): Обязательный. Строка, которую требуется записать в файл.
  • $length (int|null): Необязательный. Максимальное количество байт для записи. Если аргумент передан, запись остановится после достижения указанной длины или конца строки, в зависимости от того, что наступит раньше. Если передано null, будет записана вся строка. Начиная с PHP 8.0.0, значение null используется по умолчанию.

Возвращает количество записанных байт или false в случае ошибки.

Примеры использования fputs

Базовая запись в файл

Пример открывает файл для записи и записывает строку.

<?php
$file = fopen('example.txt', 'w');
if ($file) {
    $bytesWritten = fputs($file, 'Привет, мир!');
    fclose($file);
    echo "Записано байт: $bytesWritten"; // Записано байт: 21 (или другое значение, зависит от кодировки)
}
?>
Записано байт: 21
Запись с ограничением длины

Пример записывает только указанное количество байт из строки.

<?php
$file = fopen('example2.txt', 'w');
if ($file) {
    // Строка содержит 21 байт в UTF-8 (например).
    $bytesWritten = fputs($file, 'Привет, мир! Это PHP.', 10);
    fclose($file);
    echo "Записано байт: $bytesWritten\n";
    echo "Содержимое файла: " . file_get_contents('example2.txt');
}
?>
Записано байт: 10
Содержимое файла: Привет, м
Обработка ошибки записи

Пример демонстрирует проверку на ошибку.

<?php
$file = fopen('/readonly/readonly.txt', 'w'); // Предположим, файл доступен только для чтения
if ($file) {
    $result = fputs($file, 'Текст');
    if ($result === false) {
        echo "Ошибка записи в файл.";
    }
    fclose($file);
}
?>
Ошибка записи в файл.

Похожие функции в PHP

Функция fwrite() идентична fputs(). Является основной функцией, тогда как fputs – её исторический псевдоним. Рекомендуется использовать fwrite для ясности кода.

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

<?php
// Эквивалент простой записи через fopen/fputs/fclose
file_put_contents('file.txt', 'Данные');
?>
printf / fprintf

Функции семейства printf предназначены для форматированного вывода. fprintf() записывает отформатированную строку в указанный поток.

<?php
$file = fopen('data.txt', 'w');
fprintf($file, "Строка: %s, Число: %d", "текст", 123);
fclose($file);
?>

Аналоги в других языках

Fputs в Python

В Python для работы с файлами используют метод write() файлового объекта или функцию open() в менеджере контекста. Нет прямого аналога записи с ограничением длины в байтах для строки, но можно использовать срезы.

# Python
# Открытие файла на запись и запись строки
with open('example.txt', 'w', encoding='utf-8') as f:
    bytes_written = f.write('Привет, мир!')
print(f"Записано символов (не байт): {bytes_written}")
Записано символов (не байт): 12
JavaScript (Node.js)

В Node.js для записи в файл используют асинхронный метод fs.writeFile() или синхронный fs.writeFileSync() модуля fs. Для записи в поток (аналог файлового дескриптора) применяют метод write() потока (stream).

// JavaScript (Node.js)
const fs = require('fs');
// Аналог file_put_contents
fs.writeFileSync('example.txt', 'Привет, мир!', 'utf8');
// Запись через файловый дескриптор
const fd = fs.openSync('example2.txt', 'w');
const bytesWritten = fs.writeSync(fd, 'Hello World');
fs.closeSync(fd);
console.log(`Записано байт: ${bytesWritten}`);
Записано байт: 11

Fputs в MySQL

В MySQL запись результата запроса в файл осуществляют с помощью конструкции INTO OUTFILE. Это операция сервера, а не клиентская функция.

-- MySQL
SELECT * FROM my_table
INTO OUTFILE '/tmp/result.csv'
FIELDS TERMINATED BY ',';

Типичные ошибки

Передача некорректного ресурса

Попытка записи в несуществующий или закрытый дескриптор приводит к ошибке и возврату false.

<?php
$file = fopen('example.txt', 'r'); // Открыт только для чтения
$result = fputs($file, 'Запись'); // Предупреждение и false
if ($result === false) {
    echo "Не удалось выполнить запись.\n";
}
fclose($file);
?>
Warning: fputs(): write of 12 bytes failed with errno=9 Bad file descriptor in ...
Не удалось выполнить запись.
Невнимательность к кодировке и длине

Ограничение длины в байтах может привести к обрыву многобайтового символа UTF-8, что испортит данные.

<?php
$file = fopen('broken.txt', 'w');
$str = 'Пример';
fputs($file, $str, 5); // Символ 'П' в UTF-8 занимает 2 байта, 'р' - 2 байта. 5 байт обрежут символ.
fclose($file);
echo bin2hex(file_get_contents('broken.txt')) . "\n";
?>
d09fd180d0
Игнорирование возвращаемого значения

Недостаток места на диске или другие системные ошибки могут привести к неполной записи.

<?php
$file = fopen('large.txt', 'w');
$largeString = str_repeat('x', 1000000);
$bytes = fputs($file, $largeString);
if ($bytes !== strlen($largeString)) {
    echo "Записано $bytes байт из " . strlen($largeString) . "\n";
}
fclose($file);
?>

Изменения в последних версиях PHP

PHP 8.0.0

Значение по умолчанию для необязательного аргумента $length изменено с 0 на null. В версиях до PHP 8.0.0 передача 0 означала запись всей строки. Теперь явное указание 0 приводит к записи 0 байт (фактически, ничего не записывается). Для записи всей строки аргумент следует опустить или передать null.

<?php
// Поведение в PHP 8.0+
$file = fopen('test.txt', 'w');
fputs($file, 'abc', 0); // Записывает 0 байт
fputs($file, 'abc', null); // Записывает 'abc'
fputs($file, 'abc'); // Записывает 'abc'
fclose($file);
?>

Расширенные примеры

Запись в сокет

Функция fputs может использоваться для записи данных в сетевой сокет.

Пример php
<?php
$socket = fsockopen('tls://smtp.gmail.com', 587, $errno, $errstr, 30);
if ($socket) {
    fputs($socket, "EHLO localhost\r\n");
    echo fgets($socket, 4096);
    fclose($socket);
}
?>
Построчная запись большого массива данных

Пример эффективной записи данных без конкатенации большой строки в памяти.

Пример php
<?php
$data = ['Строка 1', 'Строка 2', 'Строка 3'];
$file = fopen('log.txt', 'w');
if ($file) {
    foreach ($data as $line) {
        fputs($file, $line . PHP_EOL); // Добавляем символ конца строки
    }
    fclose($file);
}
?>
Использование с контекстом потока (stream context)

Можно записывать данные в поток, созданный с использованием контекста, например, для HTTP-запроса.

Пример php
<?php
$postData = http_build_query(['key' => 'value']);
$context = stream_context_create([
    'http' => [
        'method' => 'POST',
        'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
        'content' => $postData,
    ],
]);
// Открываем поток для записи (отправки) данных
$stream = fopen('http://httpbin.org/post', 'r', false, $context);
if ($stream) {
    // Ответ сервера можно читать из $stream
    $response = stream_get_contents($stream);
    fclose($stream);
    echo $response; // Вывод JSON-ответа
}
?>
Запись бинарных данных

Функция корректно работает с бинарными данными, так как является бинарно-безопасной.

Пример php
<?php
$file = fopen('image_copy.jpg', 'wb');
$originalData = file_get_contents('original.jpg');
if ($file && $originalData !== false) {
    $chunkSize = 8192;
    for ($written = 0; $written < strlen($originalData); $written += $chunkSize) {
        // Записываем по кускам
        fputs($file, substr($originalData, $written, $chunkSize));
    }
    fclose($file);
    echo "Бинарный файл скопирован.";
}
?>

PHP fputs function comments

En
Fputs Alias of fwrite