Разбор CSV в FastExcelReader
На этой странице
- Содержание
- Возможности
- Базовое использование
- Какую фабрику выбрать
- Открытие CSV как обычного файла через Excel::open()
- Продвинутое чтение
- Чтение с заголовками
- Чтение через генератор (экономно по памяти)
- Чтение в массив
- Опции конфигурации
- Автоопределение разделителя
- Поддержка кодировок
- Режимы разбора (строгий и толерантный)
- Обработка ошибок
- Примеры
- Чтение файла с табуляцией (TSV)
- Обработка файлов в кодировке Windows-1251
- Пропуск комментариев
- Справочник API
Быстрый и эффективный CSV-ридер для PHP, встроенный в пакет fast-excel-reader. Он поддерживает различные кодировки, автоопределение разделителя и обработку больших файлов.
Содержание
- Возможности
- Базовое использование
- Продвинутое чтение
- Опции конфигурации
- Обработка ошибок
- Примеры
- Справочник API
Возможности
- Определение разделителя: автоматическое или ручное указание разделителя колонок.
- Широкая поддержка кодировок:
- UTF-8, UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BE
- Windows-1251, KOI8-R, ISO-8859-5
- CP932, Shift_JIS, EUC-JP
- Любая кодировка, поддерживаемая вашим окружением PHP.
- Соответствие RFC 4180: поддержка полей с кавычками и без, а также экранированных кавычек (удвоенных).
- Многострочные поля: обработка переносов строк внутри полей в кавычках.
- Гибкий разбор:
- Строгий режим: строго следует RFC 4180.
- Толерантный режим: более снисходителен к нестандартным CSV-файлам (например, кавычки внутри полей без кавычек).
- Экономия памяти: способен читать очень большие файлы построчно с помощью генераторов.
- Дополнительные утилиты: пропуск пустых строк, пропуск строк-комментариев, обрезка полей, произвольные ограничители и экранирующие символы.
- Обработка BOM: автоматическая обработка файлов с меткой порядка байтов (Byte Order Mark).
Базовое использование
Какую фабрику выбрать
Excel::openCsvBook($file, $options) возвращает типизированную CSV-книгу с общим API
sheet()/readRows(). Excel::openCsvReader($file, $options) открывает низкоуровневый
движок с getCsvLine()/fromRow(). Обе фабрики принимают массив, CsvOptions или null
и допускают пустой CSV. Универсальный Excel::open() определяет формат по содержимому
и отклоняет пустой файл; ['format' => 'csv'] принудительно выбирает CSV.
В 4.x старый Excel::openCsv() сохраняет возврат CsvReader. В 5.0 планируется возврат
CsvBook: для сохранения низкоуровневого контракта замените имя на openCsvReader().
Для общего API книги сразу используйте openCsvBook(). Доступ к движку уже открытой
книги остаётся доступен через $book->getReader().
$book = Excel::openCsvBook('data.csv', ['delimiter' => ';']);
$rows = $book->sheet()->readRows();
$reader = Excel::openCsvReader('data.csv', ['delimiter' => ';']);
$line = $reader->getCsvLine();
Проще всего открыть CSV-файл через метод Excel::openCsvReader().
use avadim\FastExcelReader\Excel;
$file = 'data.csv';
$csv = Excel::openCsvReader($file);
foreach ($csv->nextRow() as $rowNum => $row) {
// $row — это простой числовой массив
print_r($row);
}
Открытие CSV как обычного файла через Excel::open()
Начиная с v4.2.0 универсальная точка входа Excel::open() принимает и CSV-файлы, возвращая обычный
файл, — то есть CSV ведёт себя как любая другая таблица: у него один лист с тем же API, что у XLSX и
XLS (sheet(), nextRow(), readRows(), readColumns(), setReadArea(), withHeader(), режимы
ключей). Именно это позволяет форматонезависимому коду принимать CSV без спец-кейсов.
use avadim\FastExcelReader\Excel;
$book = Excel::open('data.csv'); // вернёт Csv\CsvBook
$sheet = $book->sheet(); // единственный лист CSV с именем "CSV"
$rows = $book->readRows();
// ключи — буквы столбцов Excel, ровно как для XLSX:
// [1 => ['A' => 'ID', 'B' => 'Name'], 2 => ['A' => '1', 'B' => 'John'], ...]
Формат определяется по сигнатуре файла, а не по расширению: OLE2-файл — это XLS, ZIP-файл — XLSX, всё
остальное читается как текст с разделителями. Опции передаются вторым аргументом — в том числе любой
параметр конфигурации и ['format' => 'csv'] для принудительного выбора
CSV-ридера:
$book = Excel::open('data.txt', ['delimiter' => "\t", 'encoding' => 'Windows-1251']);
$book = Excel::open($file, ['format' => 'csv']); // принудительно CSV, независимо от сигнатуры
Поскольку детекция работает по исключению, не-табличный файл попадает в CSV-ридер. Бинарный ввод —
NUL-байт или высокая доля управляющих символов — отсекается сразу понятной ошибкой, а не разбирается в
мусор; текст UTF-16/UTF-32 при этом не затрагивается (его NUL-байты легитимны). Чтобы отключить эту
проверку, задайте ['allow_binary' => true].
open() против openCsv(). Оба читают один и тот же файл; различаются тем, что возвращают, и
ключами столбцов по умолчанию:
Excel::open($csv) |
Excel::openCsvReader($csv) |
|
|---|---|---|
| Возвращает | Csv\CsvBook (объект файла) |
Csv\CsvReader (движок) |
| Ключи столбцов по умолчанию | буквы Excel A, B, ... |
числа с нуля 0, 1, ... |
| API | полный общий API AbstractSheet |
низкоуровневый API CsvReader |
openCsv() не изменён и остаётся способом добраться до низкоуровневого движка (getCsvField(),
getCsvLine(), onError(), setBufferSize(), ...). Из CsvBook тот же движок доступен через
$book->getReader().
Чего у CSV нет. CSV не хранит форматов ячеек, поэтому нет ни автоматической типизации
чисел/дат (любое значение — строка), ни стилей: readRowsWithStyles(), readCellStyles() и
readStyles() возвращают пустые стили, а не бросают исключение; нет объединённых ячеек и изображений.
Размер листа CSV тоже не хранит, поэтому dimension() пуст, пока вы явно не запросите фактический
диапазон через actualDimension(), countRows() или countColumns() — они один раз сканируют файл
(потоковый путь nextRow() этого не делает).
Продвинутое чтение
Чтение с заголовками
Если в CSV есть строка заголовков, можно использовать метод withHeader(), чтобы значения первой строки стали ключами для последующих строк.
$csv = Excel::openCsvReader($file);
$rows = $csv->withHeader()->nextRow();
foreach ($rows as $rowNum => $row) {
// $row = ['ID' => '1', 'Name' => 'John', 'City' => 'New York']
echo $row['Name'];
}
Имена столбцов можно задать и самостоятельно. Первая строка при этом всё равно пропускается, но имена берутся из вашего списка, а не из её значений. Имена применяются по порядку столбцов, поэтому буквы столбцов не нужны:
$rows = $csv->withHeader(['id', 'name', 'city'])->readRows();
// $row = ['id' => '1', 'name' => 'John', 'city' => 'New York']
Более короткий список переименует только те столбцы, которые он покрывает; остальные сохранят имя из строки заголовков.
Чтение через генератор (экономно по памяти)
Метод nextRow() возвращает \Generator, что идеально для обработки больших файлов без загрузки их целиком в память.
$csv = Excel::openCsvReader($file);
$generator = $csv->nextRow();
foreach ($generator as $row) {
// Обработать каждую строку
}
Чтение в массив
Если файл небольшой и нужны все данные сразу:
$csv = Excel::openCsvReader($file);
$allRows = $csv->readRows();
Опции конфигурации
В openCsv() можно передать массив опций или объект CsvOptions.
use avadim\FastExcelReader\Csv\CsvOptions;
$options = [
'delimiter' => ';',
'enclosure' => '"',
'encoding' => 'UTF-8',
'trim_fields' => true,
'skip_empty_lines' => true,
];
$csv = Excel::openCsvReader($file, $options);
// Другие способы задать опции:
$options = new CsvOptions($options)
->setDelimiter(';')
->setEnclosure('"')
->setEncoding('UTF-8')
->setTrimFields(true)
->setSkipEmptyLines(true)
;
$csv = Excel::openCsvReader($file, $options);
Доступные опции:
| Опция | Тип | По умолч. | Описание |
|---|---|---|---|
mode |
string |
'strict' |
Режим разбора: 'strict' или 'tolerant' |
delimiter |
string |
null |
Разделитель колонок (например, ,, ;, \t). null или 'auto' — автоопределение. |
enclosure |
string |
" |
Символ ограничителя поля. |
encoding |
string |
null |
Кодировка входного файла. null — автоопределение. |
double_quotes |
bool |
true |
Обрабатывать ли удвоенные кавычки как экранированные. |
escape |
string |
'' |
Экранирующий символ (например, \). |
trim_fields |
bool |
true |
Обрезать ли начальные/конечные пробелы у полей без кавычек. |
skip_empty_lines |
bool |
true |
Пропускать ли пустые строки. |
comment_prefix |
string |
null |
Символ(ы), обозначающие строку-комментарий (например, #). |
allow_binary |
bool |
false |
Читать бинарно выглядящий ввод, а не отклонять его (обычно NUL-байт или много управляющих символов приводят к исключению). |
Автоопределение разделителя
Если delimiter равен null или 'auto', ридер попытается определить разделитель, анализируя первые несколько строк файла.
Поддержка кодировок
Ридер автоматически определяет большинство распространённых кодировок, включая UTF-8, UTF-16 и различные региональные кодировки вроде Windows-1251 или Shift_JIS. Также можно вручную указать любую кодировку, поддерживаемую функцией PHP mb_convert_encoding.
Режимы разбора (строгий и толерантный)
- Строгий режим (
'strict'): выбрасывает ошибки, если CSV не строго следует RFC 4180 (например, если после закрывающей кавычки есть текст или внутри поля есть неэкранированные кавычки). - Толерантный режим (
'tolerant'): пытается восстановиться и прочитать как можно больше данных при встрече с некорректной структурой CSV.
Обработка ошибок
Можно задать собственный обработчик ошибок для управления проблемами разбора, что особенно полезно в tolerant-режиме.
$csv = Excel::openCsvReader($file);
$csv->onError(function($code, $error, $line, $lineNo, $colNo) {
echo "Error on line $lineNo, col $colNo: $error\n";
echo "Line content: $line\n";
});
Примеры
Чтение файла с табуляцией (TSV)
$csv = Excel::openCsvReader('data.tsv', ['delimiter' => "\t"]);
foreach ($csv->nextRow() as $row) {
// ...
}
Обработка файлов в кодировке Windows-1251
$csv = Excel::openCsvReader('russian_data.csv', ['encoding' => 'Windows-1251']);
foreach ($csv->nextRow() as $row) {
// ...
}
Пропуск комментариев
$csv = Excel::openCsvReader('config.csv', ['comment_prefix' => '#']);
foreach ($csv->nextRow() as $row) {
// Строки, начинающиеся с #, будут проигнорированы
}