fscanf()
Функция fscanf() в PHP читает данные из файла по заданному формату и разбирает их на типизированные поля.
Что такое функция fscanf()?
Функция fscanf() читает данные из открытого файла и разбирает их содержимое по строке формата в стиле printf. Вместо того чтобы возвращать необработанную строку текста, как это делает fgets(), fscanf() за один шаг разделяет ввод на типизированные поля — строки, целые числа, числа с плавающей точкой. Это предпочтительный инструмент PHP, когда файл имеет фиксированную, столбцовую структуру и нужно получить каждое значение уже преобразованным в нужный тип.
На этой странице рассматриваются синтаксис, спецификаторы формата, два способа получения результатов fscanf(), наиболее распространённые подводные камни и сравнение с похожими функциями.
Синтаксис
fscanf(resource $stream, string $format, mixed &...$vars): array|int|false| Параметр | Описание |
|---|---|
$stream | Указатель на файл, возвращённый функцией fopen(). |
$format | Строка формата, составленная из спецификаторов, таких как %s, %d и %f. |
&...$vars | Необязательно. Одна или несколько переменных, переданных по ссылке для получения разобранных полей. |
Возвращаемое значение зависит от способа вызова:
- С дополнительными аргументами-переменными → возвращает количество успешно присвоенных полей или
falseпри достижении конца файла. - Без дополнительных переменных → возвращает array разобранных полей вместо записи в переменные.
fscanf() перемещает указатель файла за пределы прочитанного фрагмента, поэтому повторные вызовы последовательно обходят файл токен за токеном.
Спецификаторы формата
Строка формата — это сердце fscanf(). Наиболее распространённые спецификаторы:
| Спецификатор | Читает |
|---|---|
%s | Строку (string) (останавливается на следующем пробельном символе) |
%d | Знаковое десятичное целое число |
%f | Число с плавающей точкой |
%c | Одиночный символ |
%x | Шестнадцатеричное целое число |
%% | Литеральный символ % |
Пробельные символы в строке формата соответствуют любой последовательности пробельных символов (пробелов, табуляций, переносов строк) во вводе, поэтому %s ограничивается пробельными символами, а не концом строки.
Чтение файла с помощью переменных
Типичный шаблон: открыть файл, выполнять цикл, пока fscanf() возвращает ожидаемое количество полей, затем закрыть файл. Предположим, data.txt содержит по одной записи в строке:
John Smith 30 50000.5
Jane Doe 28 62000Каждую строку можно разобрать в типизированные переменные следующим образом:
<?php
$file = fopen('data.txt', 'r');
if ($file === false) {
die("Error: Could not open file.");
}
while (fscanf($file, "%s %s %d %f", $first, $last, $age, $salary) === 4) {
echo "Name: $first $last, Age: $age, Salary: $salary\n";
}
fclose($file);
?>Вывод:
Name: John Smith, Age: 30, Salary: 50000.5
Name: Jane Doe, Age: 28, Salary: 62000Сравнение возвращаемого значения с 4 (количество полей, ожидаемых форматом) — ключ к безопасному циклу: в конце файла fscanf() возвращает false, а при неверно сформированной строке — меньшее число, поэтому цикл завершается корректно, а не выполняется бесконечно.
Чтение файла в array
Если не передавать аргументы-переменные, fscanf() возвращает каждую разобранную запись как array. Это удобно, когда нужно собирать строки, а не обрабатывать их по одной переменной за раз:
<?php
$file = fopen('data.txt', 'r');
while ($row = fscanf($file, "%s %s %d %f")) {
// $row is [first, last, age, salary]
[$first, $last, $age, $salary] = $row;
echo "$last, $first earns $salary\n";
}
fclose($file);
?>Вывод:
Smith, John earns 50000.5
Doe, Jane earns 62000fscanf() и sscanf()
fscanf() читает из указателя файла; sscanf() выполняет ту же самую разборку, но над строкой (string), уже находящейся в памяти. Если данные хранятся в переменной, а не в файле, используйте sscanf():
<?php
$count = sscanf("2024-06-21", "%d-%d-%d", $year, $month, $day);
echo "$count fields parsed: $year / $month / $day\n";
?>Вывод:
3 fields parsed: 2024 / 6 / 21Распространённые подводные камни
%sостанавливается на пробельном символе, а не в конце строки. Имя вродеNew Yorkбудет прочитано как два поля%s, а не одно. Формат должен точно соответствовать реальной структуре данных.- Всегда проверяйте возвращаемое значение. Цикл по количеству полей (
=== 4), а не по!feof(), защищает от неполных строк и бесконечных циклов. - Сначала проверьте
fopen().fscanf()требует действительного ресурса; неудачное открытие возвращаетfalse. - Для данных, разделённых запятыми, предпочтительнее
fgetcsv().fscanf()предназначен для разделённых пробелами столбцов фиксированного формата, а не для полей CSV с кавычками.
Связанные функции
sscanf()— разбор форматированной строки вместо файла.fgetcsv()— чтение и разбиение строк CSV.fgets()— чтение необработанной строки текста.fopen()/fclose()— открытие и закрытие файлового потока.
Заключение
fscanf() преобразует содержимое файла с пробельными разделителями в типизированные значения PHP за один вызов. Используйте форму с переменными, когда записи обрабатываются по одной, или форму с array, когда нужно их собрать. Всегда проверяйте возвращаемое значение для управления циклом, и переключайтесь на sscanf() для строк в памяти или fgetcsv() для настоящего CSV.