diff --git a/src/Parser.php b/src/Parser.php index 6e32a4e..49a7daf 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -44,6 +44,9 @@ public function __construct( public function parseRow(): Promise { return call(function () { + if ($this->fileHandle->eof()) { + return null; + } $buffer = ''; $newLinePos = null; while ($chunk = yield $this->fileHandle->read()) { @@ -53,12 +56,12 @@ public function parseRow(): Promise break; } } - $bufferSize = \strlen($buffer); - $seekOffset = $bufferSize-$newLinePos; - yield $this->fileHandle->seek(-($seekOffset-1), \SEEK_CUR); - $row = substr($buffer, 0, $newLinePos); - if (empty($row)) { - return null; + $row = $buffer; + if ($newLinePos !== false) { + $bufferSize = \strlen($buffer); + $seekOffset = $bufferSize-$newLinePos; + yield $this->fileHandle->seek(-($seekOffset-1), \SEEK_CUR); + $row = substr($buffer, 0, $newLinePos); } $this->rowsParsed++; return str_getcsv($row, $this->delimiter, $this->enclosure, $this->escape); diff --git a/tests/ParserTest.php b/tests/ParserTest.php index 98784ae..1085b0b 100644 --- a/tests/ParserTest.php +++ b/tests/ParserTest.php @@ -79,4 +79,23 @@ public function testParseRowsWithDifferentDelimiter() $rows[2] ); } + + public function testParseFileWithEmptyRows() + { + $rows = []; + Loop::run(function () use (&$rows) { + $parser = new Parser(yield File\open(__DIR__ . '/empty-rows.csv', 'rb')); + while ($row = yield $parser->parseRow()) { + $rows[] = $row; + } + $this->assertEquals(10, $parser->getRowsParsed()); + }); + $this->assertCount(10, $rows); + $this->assertEquals(['sku', 'qty'], $rows[0]); + $this->assertEquals(['AAA', '123'], $rows[1]); + $this->assertEquals(['', '2'], $rows[3]); + $this->assertEquals(['A'], $rows[4]); + $this->assertEquals([''], $rows[8]); + $this->assertEquals(['test'], $rows[9]); + } } diff --git a/tests/empty-rows.csv b/tests/empty-rows.csv new file mode 100644 index 0000000..ebbc8a9 --- /dev/null +++ b/tests/empty-rows.csv @@ -0,0 +1,10 @@ +sku,qty +AAA,123 +BBB,1 +,2 +A + + + + +test