diff --git a/docs/topics/reading-and-writing-to-file.md b/docs/topics/reading-and-writing-to-file.md index df595a81..df8ed7c2 100644 --- a/docs/topics/reading-and-writing-to-file.md +++ b/docs/topics/reading-and-writing-to-file.md @@ -544,6 +544,25 @@ $reader->setSheetIndex(5); $reader->loadIntoExisting("05featuredemo.csv", $spreadsheet); ``` +#### Line endings + +Line endings for Unix (`\n`) and Windows (`\r\n`) are supported. + +Mac line endings (`\r`) are supported as long as PHP itself +supports them, which it does through release 8.0. +Support for Mac line endings is deprecated for 8.1, +and is scheduled to remain deprecated for all later PHP8 releases; +PhpSpreadsheet will continue to support them for 8.*. +Support is scheduled to be dropped with release 9; +PhpSpreadsheet will then no longer handle CSV files +with Mac line endings correctly. + +You can suppress testing for Mac line endings as follows: +```php +$reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv(); +$reader->setTestAutoDetect(false); +``` + ### \PhpOffice\PhpSpreadsheet\Writer\Csv #### Writing a CSV file diff --git a/src/PhpSpreadsheet/Reader/Csv.php b/src/PhpSpreadsheet/Reader/Csv.php index 0146fca0..e79f7942 100644 --- a/src/PhpSpreadsheet/Reader/Csv.php +++ b/src/PhpSpreadsheet/Reader/Csv.php @@ -84,6 +84,13 @@ class Csv extends BaseReader */ private static $constructorCallback; + /** + * Attempt autodetect line endings (deprecated after PHP8.1)? + * + * @var bool + */ + private $testAutodetect = true; + /** * Create a new CSV Reader instance. */ @@ -269,10 +276,15 @@ class Csv extends BaseReader } } - private static function setAutoDetect(?string $value): ?string + public function setTestAutoDetect(bool $value): void + { + $this->testAutodetect = $value; + } + + private function setAutoDetect(?string $value): ?string { $retVal = null; - if ($value !== null) { + if ($value !== null && $this->testAutodetect) { $retVal2 = @ini_set('auto_detect_line_endings', $value); if (is_string($retVal2)) { $retVal = $retVal2; @@ -288,7 +300,7 @@ class Csv extends BaseReader public function loadIntoExisting(string $filename, Spreadsheet $spreadsheet): Spreadsheet { // Deprecated in Php8.1 - $iniset = self::setAutoDetect('1'); + $iniset = $this->setAutoDetect('1'); // Open file $this->openFileOrMemory($filename); @@ -339,7 +351,7 @@ class Csv extends BaseReader // Close file fclose($fileHandle); - self::setAutoDetect($iniset); + $this->setAutoDetect($iniset); // Return return $spreadsheet; diff --git a/tests/PhpSpreadsheetTests/Reader/Csv/CsvLineEndingTest.php b/tests/PhpSpreadsheetTests/Reader/Csv/CsvLineEndingTest.php index 38f2aaa1..8934e453 100644 --- a/tests/PhpSpreadsheetTests/Reader/Csv/CsvLineEndingTest.php +++ b/tests/PhpSpreadsheetTests/Reader/Csv/CsvLineEndingTest.php @@ -36,6 +36,31 @@ class CsvLineEndingTest extends TestCase $spreadsheet->disconnectWorksheets(); } + /** + * @dataProvider providerEndings + */ + public function testEndingsNoDetect(string $ending): void + { + $this->tempFile = $filename = File::temporaryFilename(); + $data = ['123', '456', '789']; + file_put_contents($filename, implode($ending, $data)); + $reader = new Csv(); + $reader->setTestAutoDetect(false); + $spreadsheet = $reader->load($filename); + $sheet = $spreadsheet->getActiveSheet(); + if ($ending === "\r") { + // Can't handle Mac line endings without autoDetect + self::assertEquals(implode("\n", $data), $sheet->getCell('A1')->getValue()); + self::assertNull($sheet->getCell('A2')->getValue()); + self::assertNull($sheet->getCell('A3')->getValue()); + } else { + self::assertEquals($data[0], $sheet->getCell('A1')->getValue()); + self::assertEquals($data[1], $sheet->getCell('A2')->getValue()); + self::assertEquals($data[2], $sheet->getCell('A3')->getValue()); + } + $spreadsheet->disconnectWorksheets(); + } + public function providerEndings(): array { return [