SplFileObject::fgetcsv

(PHP 5 >= 5.1.0, PHP 7, PHP 8)

SplFileObject::fgetcsv β€” ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ строку ΠΈΠ· Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ указатСля ΠΈ Ρ€Π°Π·Π±ΠΈΡ€Π°Π΅Ρ‚ ΠΏΠΎ CSV-полям

ОписаниС

public function SplFileObject::fgetcsv(string $separator = ",", string $enclosure = "\"", string $escape = "\\"): array|false

ΠœΠ΅Ρ‚ΠΎΠ΄ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ строку ΠΈΠ· CSV-Ρ„Π°ΠΉΠ»Π° ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ массив с ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°Π½Π½Ρ‹ΠΌΠΈ полями.

Π—Π°ΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅: Ѐункция ΡƒΡ‡ΠΈΡ‚Ρ‹Π²Π°Π΅Ρ‚ Ρ€Π΅Π³ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ настройки. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ функция ΠΈΠ½ΠΎΠ³Π΄Π° Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ Ρ€Π°Π·Π±ΠΈΡ€Π°Π΅Ρ‚ Π΄Π°Π½Π½Ρ‹Π΅ Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΎΠ΄Π½ΠΎΠ±Π°ΠΉΡ‚ΠΎΠ²Ρ‹Ρ… ΠΊΠΎΠ΄ΠΈΡ€ΠΎΠ²ΠΊΠ°Ρ…, Ссли Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ константы LC_CTYPE Ρ€Π°Π²Π½ΠΎ en_US.UTF-8.

Бписок ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ²

separator

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ устанавливаСт символ-Ρ€Π°Π·Π΄Π΅Π»ΠΈΡ‚Π΅Π»ΡŒ ΠΏΠΎΠ»Π΅ΠΉ ΠΈ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ ΠΎΠ΄Π½ΠΎΠ±Π°ΠΉΡ‚ΠΎΠ²Ρ‹ΠΉ символ. Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Ρ€Π°Π²Π½ΠΎ запятой β€” , ΠΈΠ»ΠΈ символу, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ установили ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠΌ SplFileObject::setCsvControl().

enclosure

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ устанавливаСт символ-ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΡ‚Π΅Π»ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ Π² полях ΠΈ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ ΠΎΠ΄Π½ΠΎΠ±Π°ΠΉΡ‚ΠΎΠ²Ρ‹ΠΉ символ. Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Ρ€Π°Π²Π½ΠΎ Π΄Π²ΠΎΠΉΠ½ΠΎΠΉ ΠΊΠ°Π²Ρ‹Ρ‡ΠΊΠ΅ β€” " ΠΈΠ»ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΡŽ, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ установили ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠΌ SplFileObject::setCsvControl().

escape

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ устанавливаСт символ экранирования ΠΈ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π½Π΅ большС ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΎΠ΄Π½ΠΎΠ±Π°ΠΉΡ‚ΠΎΠ²ΠΎΠ³ΠΎ символа. Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Ρ€Π°Π²Π½ΠΎ ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠΌΡƒ ΡΠ»Π΅ΡˆΡƒ \ ΠΈΠ»ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΡŽ, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ установили ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠΌ SplFileObject::setCsvControl(). ΠŸΡƒΡΡ‚Π°Ρ строка "" ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠΉ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ экранирования.

Π’Π½ΠΈΠΌΠ°Π½ΠΈΠ΅

ΠžΠ±Ρ‹Ρ‡Π½ΠΎ символ ограничитСля Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ β€” enclosure экранируСтся Π²Π½ΡƒΡ‚Ρ€ΠΈ поля ΠΏΡƒΡ‚Ρ‘ΠΌ удвоСния; ΠΎΠ΄Π½Π°ΠΊΠΎ ΠΊΠ°ΠΊ Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Ρƒ Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ΡΡ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ символ экранирования escape. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ для стандартных Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° смысл Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ "" ΠΈ \" ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ². Π‘ΠΈΠΌΠ²ΠΎΠ» экранирования β€” escape Π½Π΅ нСсёт ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ смысла, ΠΊΡ€ΠΎΠΌΠ΅ экранирования символа ограничитСля Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ β€” enclosure; ΠΎΠ½ Π΄Π°ΠΆΠ΅ Π½Π΅ экранируСт сам сСбя.

Π’Π½ΠΈΠΌΠ°Π½ΠΈΠ΅

Начиная с PHP 8.4.0 ΠΏΠΎΠ»Π°Π³Π°Ρ‚ΡŒΡΡ Π½Π° Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ содСрТит ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ escape, Π½Π΅ Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΡŽΡ‚. Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ потрСбуСтся ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ явно: ΠΏΠΎΠ·ΠΈΡ†ΠΈΠΎΠ½Π½ΠΎ, ΠΊΠ°ΠΊ ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ ΠΈΠ»ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠΌ SplFileObject::setCsvControl().

Π’Π½ΠΈΠΌΠ°Π½ΠΈΠ΅

Π‘Ρ‚Ρ€ΠΎΠΊΠ° Π² CSV-Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅ ΠΈΠ½ΠΎΠ³Π΄Π° пСрСстаёт ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ стандарту » RFC 4180 ΠΈΠ»ΠΈ Π½Π΅ Π²Ρ‹Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ ΠΎΠ±ΠΌΠ΅Π½Π° ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠ΅ΠΉ с PHP-функциями для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с CSV-строками, Ссли для символа экранирования escape ΡƒΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°ΡŽΡ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ отличаСтся ΠΎΡ‚ пустой строки "". Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ для ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° escape β€” "\\", поэтому Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΡŽΡ‚ явно ΡƒΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ ΠΏΡƒΡΡ‚ΡƒΡŽ строку. Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ измСнят Π² Π±ΡƒΠ΄ΡƒΡ‰Π΅ΠΉ вСрсии PHP, Π½ΠΎ Π½Π΅ Ρ€Π°Π½ΡŒΡˆΠ΅ PHP 9.0.

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Π΅ значСния

ΠœΠ΅Ρ‚ΠΎΠ΄ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ массив, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ содСрТит Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°Π½Π½ΠΎΠΉ строки, ΠΈΠ»ΠΈ false, Ссли Π²ΠΎΠ·Π½ΠΈΠΊΠ»Π° ошибка.

Π—Π°ΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅:

ΠŸΡƒΡΡ‚Π°Ρ строка Π² CSV-Ρ„Π°ΠΉΠ»Π΅ возвращаСтся ΠΊΠ°ΠΊ массив с СдинствСнным элСмСнтом null, Ссли Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‡Π΅Ρ€Π΅Π· ΠΏΠΎΠ±ΠΈΡ‚ΠΎΠ²ΠΎΠ΅ Π˜Π›Π˜ Π½Π΅ ΡƒΠΊΠ°Π·Π°Π»ΠΈ константы SplFileObject::SKIP_EMPTY | SplFileObject::DROP_NEW_LINE, с ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌΠΈ пустыС строки ΠΏΡ€ΠΎΠΏΡƒΡΠΊΠ°ΡŽΡ‚ΡΡ.

Ошибки

Ѐункция выбрасываСт ΠΎΡˆΠΈΠ±ΠΊΡƒ ValueError, Ссли Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Ρ‹ для раздСлитСля ΠΏΠΎΠ»Π΅ΠΉ separator ΠΈΠ»ΠΈ ограничитСля Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ enclosure содСрТат Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΊΠΎΡ€ΠΎΡ‡Π΅ ΠΎΠ΄Π½ΠΎΠ³ΠΎ Π±Π°ΠΉΡ‚Π°.

Ѐункция выбрасываСт ΠΎΡˆΠΈΠ±ΠΊΡƒ ValueError, Ссли Π΄Π»ΠΈΠ½Π° значСния Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° escape Π½Π΅ Ρ€Π°Π²Π½Π° ΠΎΠ΄Π½ΠΎΠΌΡƒ Π±Π°ΠΉΡ‚Ρƒ ΠΈΠ»ΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Π»ΠΈ ΠΏΡƒΡΡ‚ΡƒΡŽ строку.

Бписок измСнСний

ВСрсия ОписаниС
8.4.0 Π’Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π±Π΅Π· явной ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ значСния Π² ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ escape устарСл.
7.4.0 Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ escape ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ΠΏΡƒΡΡ‚ΡƒΡŽ строку для ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅Π³ΠΎ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ° экранирования.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #1 ΠŸΡ€ΠΈΠΌΠ΅Ρ€ получСния ΠΈ Ρ€Π°Π·Π±ΠΎΡ€Π° строки ΠΏΠΎ CSV-полям ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠΌ SplFileObject::fgetcsv()

<?php

$file
= new SplFileObject("data.csv");

while (!
$file->eof()) {
var_dump($file->fgetcsv());
}

?>

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #2 ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Ρ€Π°Π·Π±ΠΎΡ€Π° строк с Ρ„Π»Π°Π³ΠΎΠΌ SplFileObject::READ_CSV

<?php

$file
= new SplFileObject("animals.csv");
$file->setFlags(SplFileObject::READ_CSV);

foreach (
$file as $row) {
list(
$animal, $class, $legs) = $row;
printf("A %s is a %s with %d legs\n", $animal, $class, $legs);
}

?>

Contents of animals.csv

crocodile,reptile,4
dolphin,mammal,0
duck,bird,2
koala,mammal,4
salmon,fish,0

Π’Ρ‹Π²ΠΎΠ΄ ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΡ…ΠΎΠΆ Π½Π°:

A crocodile is a reptile with 4 legs
A dolphin is a mammal with 0 legs
A duck is a bird with 2 legs
A koala is a mammal with 4 legs
A salmon is a fish with 0 legs

Π‘ΠΌΠΎΡ‚Ρ€ΠΈΡ‚Π΅ Ρ‚Π°ΠΊΠΆΠ΅

  • SplFileObject::fputcsv() - ЗаписываСт массив ΠΏΠΎΠ»Π΅ΠΉ ΠΊΠ°ΠΊ CSV-строки
  • SplFileObject::setCsvControl() - УстанавливаСт символы раздСлитСля, ограничитСля ΠΈ экранирования для CSV-ΠΏΠΎΠ»Π΅ΠΉ
  • SplFileObject::getCsvControl() - ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ символы раздСлитСля, ограничитСля ΠΈ экранирования CSV-ΠΏΠΎΠ»Π΅ΠΉ
  • SplFileObject::setFlags() - УстанавливаСт Ρ„Π»Π°Π³ΠΈ для SplFileObject
  • SplFileObject::READ_CSV
  • SplFileObject::current() - ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰ΡƒΡŽ строку Ρ„Π°ΠΉΠ»Π°
  • fputcsv() - Π€ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅Ρ‚ строку Π² CSV-Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅ ΠΈ записываСт строку Π² Ρ„Π°ΠΉΠ»ΠΎΠ²Ρ‹ΠΉ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ
  • fgetcsv() - ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ строку ΠΈΠ· Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠ³ΠΎ указатСля ΠΈ Ρ€Π°Π·Π±ΠΈΡ€Π°Π΅Ρ‚ ΠΏΠΎ CSV-полям
  • str_getcsv() - Π Π°Π·Π±ΠΈΡ€Π°Π΅Ρ‚ CSV-строку Π² массив
οΌ‹Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΡ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ 6 notes

up
14
android991 at gmail dot com ΒΆ
7 years ago
Be aware.
There is bug 46569 persists that breaks usage of SplFileObject::fgetcsv() after SplFileObject::seek()-ing to a non-zero position and then returns the contents of wrong line - off by one
<?php
$file = new SplFileObject('foo/bar.csv');
$file->seek(1);
print_r($file->fgetcsv()); // reads 3rd line against 2nd
up
5
InvisibleSmiley ΒΆ
4 years ago
Not that this may return NULL instead of FALSE depending on the given SplFileObject flags in versions prior to PHP 8.1.

Change: https://github.com/php/php-src/commit/188b1d4c7c7b3482584e248522d94e06ba616a1c

Testcase: https://3v4l.org/6dQTT
up
3
Denitz ΒΆ
7 years ago
If your CSV doesn't have enclosures, you can face an issue with default " identified as enclosure in data. Empty $enclosure is not allowed, but you can use same $enclosure as $delimiter (\n by default) to emulate empty enclosure.
up
2
v-fpiris at teknober dot com ΒΆ
15 years ago
after setting the delimiter '\t' fgetcsv() truncates the value when it is empty string 

workaround:

<?php
$file = new SplFileObject($path);
$file->setFlags(SplFileObject::DROP_NEW_LINE);
while ($file->valid()) {
    $line = $file->fgets();
    $line = explode("\t", $line);

    print_r($line);
}
?>
up
2
vaughn dot clayton+php at servicetrade dot com ΒΆ
13 years ago
Note that due to bugs 55807 and 61032, introduced in 5.3.8, if the csv in example #2 has a newline character at the end of each line, the foreach will execute 6 times.

The last time through the loop $row will be bool(false). This is true even if using SplFileObject::SKIP_EMPTY and SplFileObject::DROP_NEW_LINE.

Until the bug is fixed, the workaround is to also add SplFileObject::READ_AHEAD to your setFlags() call.
up
1
jbrauer ΒΆ
6 years ago
Also while the enclosure character cannot be NULL you can set it to ASCII NUL character chr(0) with the same practical effect.