fgetcsv()
Функция fgetcsv() в PHP читает строку из файла и разбирает её как CSV-данные. Незаменима для импорта табличных данных на сервере.
Введение в функцию PHP fgetcsv()
Функция fgetcsv() в PHP считывает одну строку из открытого файла и разбирает её как CSV (Comma-Separated Values), возвращая поля в виде array. Это стандартный инструмент для импорта экспортированных таблиц, потоков данных и табличных текстовых файлов в PHP.
Причина использовать fgetcsv() вместо fgets() с explode(',', ...) заключается в том, что CSV сложнее, чем простое разбиение по запятым. Поле может содержать запятую, если оно заключено в кавычки ("Doe, John"), поле может занимать несколько строк, а кавычки внутри кавычечного поля удваиваются (""). fgetcsv() обрабатывает все эти правила за вас, возвращая чистые поля без необходимости писать парсер.
На этой странице рассматриваются сигнатура и параметры, возвращаемые значения и полные исполняемые примеры — чтение целого файла, использование пользовательского разделителя, а также сопоставление строки заголовка с ассоциативными строками.
Синтаксис
Синтаксис функции fgetcsv() выглядит следующим образом:
Синтаксис PHP fgetcsv()
array fgetcsv ( resource $stream [, int $length = 0 [, string $delimiter = ',' [, string $enclosure = '"' [, string $escape = '\\' ]]]] )stream: указатель на файл, из которого производится чтениеlength: максимальная длина строки для чтенияdelimiter: символ-разделитель для CSV-данныхenclosure: символ ограничителя для CSV-данныхescape: символ экранирования для CSV-данных
Параметры
Функция fgetcsv() принимает один обязательный параметр и четыре необязательных:
$stream: Указатель на файл, из которого выполняется чтение. Этот параметр может быть ресурсом, созданным функциейfopen()или аналогичной функцией.$length: Максимальная длина считываемой строки. Параметр необязателен, по умолчанию равен 0, что означает чтение всей строки целиком.$delimiter: Символ-разделитель для CSV-данных. Параметр необязателен, по умолчанию равен ','.$enclosure: Символ ограничителя для CSV-данных. Параметр необязателен, по умолчанию равен '"'.$escape: Символ экранирования для CSV-данных. Параметр необязателен, по умолчанию равен '\'. Примечание: этот параметр устарел начиная с PHP 8.1.
Возвращаемые значения
При успехе fgetcsv() возвращает индексированный array, содержащий поля, считанные из строки. Пустая строка возвращает array с единственным полем null. При достижении конца файла возвращается false — именно так вы узнаёте, когда прекратить чтение. Если поток недействителен, также возвращается false.
Поскольку и «конец файла», и «ошибка» возвращают false, идиоматический способ перебора — продолжать вызывать fgetcsv() до тех пор, пока она не вернёт false, обычно в условии while.
Примеры
Пример 1: Чтение одной строки CSV-данных
Следующий пример открывает файл, читает одну строку CSV-данных и корректно закрывает дескриптор файла. Всегда проверяйте, что fopen() выполнился успешно, прежде чем читать:
Чтение одной строки CSV-данных
$fileHandle = fopen('data.csv', 'r');
if ($fileHandle !== false) {
$row = fgetcsv($fileHandle);
print_r($row);
fclose($fileHandle);
}Для файла, первая строка которого содержит John,Doe,42, выводится:
Array
(
[0] => John
[1] => Doe
[2] => 42
)Пример 2: Перебор всех строк файла
В реальном коде редко читают только одну строку. Вызывайте fgetcsv() в цикле while до тех пор, пока она не вернёт false, чтобы обработать весь файл:
Чтение каждой строки CSV-файла
$fileHandle = fopen('data.csv', 'r');
if ($fileHandle !== false) {
while (($row = fgetcsv($fileHandle)) !== false) {
echo implode(' | ', $row), PHP_EOL;
}
fclose($fileHandle);
}Строгое сравнение !== false важно: допустимая строка вроде ["0"] является «ложной» в PHP, поэтому нестрогое условие while ($row = fgetcsv(...)) может преждевременно остановиться на корректных данных.
Пример 3: Использование пользовательского разделителя
Многие «CSV»-файлы на самом деле разделены точкой с запятой или символом табуляции. Передайте разделитель третьим аргументом (второй аргумент $length можно оставить равным 0 для отсутствия ограничения):
Чтение CSV-данных с пользовательским разделителем
// Semicolon-separated values
$row = fgetcsv($fileHandle, 0, ';');
// Tab-separated values
$row = fgetcsv($fileHandle, 0, "\t");Пример 4: Сопоставление строки заголовка с ассоциативными массивами
CSV-файлы обычно имеют строку заголовка. Считайте её один раз, затем объедините с каждой строкой данных с помощью array_combine(), чтобы обращаться к полям по имени, а не по числовому индексу:
Преобразование CSV-файла в ассоциативные строки
$fileHandle = fopen('users.csv', 'r');
if ($fileHandle !== false) {
$header = fgetcsv($fileHandle); // e.g. ['id', 'name', 'email']
while (($data = fgetcsv($fileHandle)) !== false) {
$row = array_combine($header, $data);
echo $row['name'], ' <', $row['email'], '>', PHP_EOL;
}
fclose($fileHandle);
}Распространённые ошибки
- Параметр
$escapeустарел. Начиная с PHP 8.1, передача непустого$escapeвызывает уведомление об устаревании, а PHP 9 изменит значение по умолчанию на"". Для совместимого со стандартами CSV (где кавычки экранируются удвоением,"") явно передавайтеescape: "". - UTF-8 BOM в первом поле. Файлы, экспортированные из Excel, могут начинаться с метки порядка байтов, из-за чего первое поле заголовка выглядит как
"\u{FEFF}id". Удалите её с помощьюltrim($header[0], "\u{FEFF}"), если сравнения не работают. auto_detect_line_endings. Старые Mac-переводы строк (\r) могут сбивать парсер в старых версиях PHP; этот параметрiniбыл удалён в PHP 8.1, поскольку парсер теперь обрабатывает их нативно.
Связанные функции
fopen()— открыть файл перед чтением.fgets()— считать необработанную строку без CSV-разбора.fputcsv()— обратная операция: записать array как строку CSV.fclose()— закрыть дескриптор по завершении работы.- Работа с файлами в PHP — общая картина работы с файлами.
Заключение
fgetcsv() считывает одну строку из открытого файла и разбирает её как CSV, возвращая индексированный array полей и false при достижении конца файла. Используйте цикл со строгой проверкой !== false, применяйте array_combine() для сопоставления строки заголовка с именованными полями и помните, что параметр $escape устарел — передавайте escape: "" для современного, соответствующего стандартам разбора.