PHPackages                             offdev/csv - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. offdev/csv

ActiveLibrary

offdev/csv
==========

Reads, parses and validates CSV files using streams

1.2.2(7y ago)531.4k3[2 issues](https://github.com/offdev/csv/issues)[1 PRs](https://github.com/offdev/csv/pulls)Apache-2.0PHPPHP &gt;=7.2CI failing

Since Oct 14Pushed 1y ago4 watchersCompare

[ Source](https://github.com/offdev/csv)[ Packagist](https://packagist.org/packages/offdev/csv)[ RSS](/packages/offdev-csv/feed)WikiDiscussions master Synced 3d ago

READMEChangelogDependencies (8)Versions (8)Used By (0)

Offdev/Csv
==========

[](#offdevcsv)

[![Latest Stable Version](https://camo.githubusercontent.com/a9b7e2fb30a537d14aeba5b6b9953ce8ecb28587bc1558d0057c0121a17a30ef/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f767072652f6f66666465762f6373762e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/offdev/csv)[![Minimum PHP Version](https://camo.githubusercontent.com/4f9eddea3b5f90bdf4c2f6feafb71962a03512fd923888e4aef358cf6334daf7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344253230372e322d3838393242462e7376673f7374796c653d666c61742d737175617265)](https://php.net/)[![Build Status](https://camo.githubusercontent.com/5932295a76bf9e9dd4b8a36cadfb9e5300e77ae14d71c5ecddb23c0bb955c1cf/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f6f66666465762f6373762f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://travis-ci.org/offdev/csv)[![PHPStan](https://camo.githubusercontent.com/441b5874ce4df0a2defc892979c96c46889b69cb32119d04f0b48626349f8bc9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d656e61626c65642d627269676874677265656e2e7376673f7374796c653d666c6174)](https://github.com/phpstan/phpstan)[![Mutation Score](https://camo.githubusercontent.com/393b7d9af72c6f31f23e299d2b367352f156b3ee7eb645b294f68de8e0793c2e/68747470733a2f2f62616467652e737472796b65722d6d757461746f722e696f2f6769746875622e636f6d2f6f66666465762f6373762f6d6173746572)](https://travis-ci.org/offdev/csv)[![License](https://camo.githubusercontent.com/c751bb299be7e3325a8e613f381ffcedaee68cc83f00af75d5f50d016db24582/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6f66666465762f6373762e737667)](https://www.apache.org/licenses/LICENSE-2.0)

Requirements
------------

[](#requirements)

- PHP &gt;= 7.2
- Composer

Installation
------------

[](#installation)

```
$ composer require offdev/csv
```

Introduction
------------

[](#introduction)

This parser has been written, in order to parser big CSV files from almost any data source in an easy and convenient way. It also provides the possibility to validate each record from the CSV source.

In order for the parser to work, you need to feed it with data. This data will be represented as a stream. This allows us to handle huge amounts of data. The parser can also work with HTTP streams.

Please read further to see how it is used.

Streams
-------

[](#streams)

In order to feed the parser with data, you need to give it a stream. A stream can be obtained in a different number of ways:

### Using resources

[](#using-resources)

```
use Offdev\Csv\Stream;

$stream = Stream::factory(fopen('/path/to/file.csv', 'r'));
```

### Using strings

[](#using-strings)

```
use Offdev\Csv\Stream;

$stream = Stream::factory('this string will be transformed to an in-memory stream');
```

Note: this method also works for any object which implements the `__toString` method.

### Using HTTP streams (see [PSR-7/Streams](https://www.php-fig.org/psr/psr-7/#13-streams))

[](#using-http-streams-see-psr-7streams)

```
use GuzzleHttp\Client;
use Offdev\Csv\Stream;

$client = new Client();
$response = $client->get('http://httpbin.org/get');
$stream = Stream::factory($response->getBody());
```

### Convenience

[](#convenience)

If you want to quickly create a stream, you can use the provided helper function. You need to use composer's autoloader to be able to use this.

```
// Recognizes files, and opens them in read mode
$fileStream = stream('/tmp/results.csv');

// Create from string
$stringStream = stream('stream content');

// From objcets, which implement the __toString method
class Example
{
    public function __toString(){
     return 'some example';
    }
}
$objectToStringStream = stream(new Example());
```

Parser
------

[](#parser)

### Basics

[](#basics)

Once the parser has a stream to work with, we can start using it:

```
use Offdev\Csv\Parser;

$parser = new Parser($stream);
while (!$parser->eof()) {
    $record = $parser->readLine();
    echo $record->get('header-column2').PHP_EOL;
}
```

The example above produces following output:

```
$ php example.php
row1-value2
row2-value2

```

For convenience, the parser can also be used as an iterator:

```
$parser = new Parser($stream);
foreach ($parser as $index => $record) {
    echo $record->get('header-column2').PHP_EOL;
}
```

This will produce the same output as the example above.

### Options

[](#options)

The parser accepts a number of options. The parser accepts options in an array, which is passed a a second argument to the constructor:

```
$parser = new Parser($stream, [
    Parser::OPTION_DELIMITER => ';'
]);
```

Full list of options:

OptionValue TypeDefault ValueDescription`Parser::OPTION_BUFSIZE`&lt;integer&gt;`1024`Defines the size of the buffer which is used when reading streams.`Parser::OPTION_HEADER`&lt;boolean&gt;`true`Tells the parser if the CSV contains a header. This header will be used as keys for the records read from the stream.`Parser::OPTION_DELIMITER`&lt;string&gt;`','`Defines the delimiter used in the CSV file to mark columns.`Parser::OPTION_STRING_ENCLOSURE`&lt;string&gt;`'"'`Defines the delimiter used for strings.`Parser::OPTION_ESCAPE_CHAR`&lt;string&gt;`'\\'`Defines the character used to escape other control characters.`Parser::OPTION_EOL`&lt;string&gt;`"\n"`Defines the line ending used in the CSV file. Unix files mostly use `\n` while windows mostly uses `\r\n`.`Parser::OPTION_THROWS`&lt;boolean&gt;`true`Tells the parser to throw an exception when an invalid records was found in the stream.Processor
---------

[](#processor)

For better usability and separation of concerns, the parser accepts a processor, which will receive any parsed records from the stream. Records are represented as [Laravel collections](https://laravel.com/docs/5.6/collections).

If a validator was assigned to the parser, valid and invalid records will be passed to the respective methods. If no validator was given, all records will be passed to the `parseRecord` method. Empty lines will always be ignored.

Example processor:

```
namespace MyCompany\ProjectX\Processors;

use Offdev\Csv\Item;
use Offdev\Csv\ProcessorInterface;

class MyProcessor implements ProcessorInterface
{
    public function processRecord(Item $record): void
    {
        // No header in CSV, use numeric index
        echo "Got item: ".$record->get(1).PHP_EOL;
    }

    public function processInvalidRecord(Item $record): void
    {
        $this->processRecord($record);
    }

    public function eof(): void
    {
        echo "---EOF---".PHP_EOL;
    }
}
```

Usage:

```
use MyCompany\ProjectX\Processors\MyProcessor;
use Offdev\Csv\Parser;
use Offdev\Csv\Stream;

$stream = Stream::factory("1;John\n2;Lisa\n3;Robert");
$parser = new Parser($stream, [
    Parser::OPTION_DELIMITER => ';',
    Parser::OPTION_HEADER => false
]);
$parser->setProcessor(new MyProcessor());
$parser->run();
```

The example above produces following output:

```
$ php example.php
Got item: John
Got item: Lisa
Got item: Robert
---EOF---

```

Validator
---------

[](#validator)

Now, most of the times, we want to make sure the data contained in the CSV is in a given format. This package uses the Laravel validation package in order to provide a rule engine for the content of the CSV. A full list of all rules can be found [here](https://laravel.com/docs/5.7/validation#available-validation-rules).

Usage:

```
use Offdev\Csv\Parser;
use Offdev\Csv\Stream;
use Offdev\Csv\Validator;

try {
    $stream = Stream::factory("id,name\n1,John\n2,Lisa\nNaN,Robert");
    $parser = new Parser($stream);
    $parser->setValidator(new Validator([
        'id' => 'required|numeric',
        'name' => 'required|string|min:3'
    ]));
    $parser->run();
    echo "CSV is valid!".PHP_EOL;
} catch (\Exception $e) {
    echo "CSV is invalid!".PHP_EOL;
}
```

Code quality
------------

[](#code-quality)

First, make sure to install the dependencies by running `composer install`. You also need to make sure to have xdebug activated in order for PHPUnit to generate the code coverage.

**PHP Code Sniffer**

```
$ ./vendor/bin/phpcs --colors --standard=PSR2 -v src/ tests/
Registering sniffs in the PSR2 standard... DONE (42 sniffs registered)
Creating file list... DONE (10 files in queue)
Changing into directory /Users/pascal/devel/csv-parser/src
Processing Validator.php [PHP => 436 tokens in 74 lines]... DONE in 46ms (0 errors, 0 warnings)
Processing Parser.php [PHP => 2125 tokens in 312 lines]... DONE in 140ms (0 errors, 0 warnings)
Processing Stream.php [PHP => 2248 tokens in 344 lines]... DONE in 116ms (0 errors, 0 warnings)
Processing ParserInterface.php [PHP => 552 tokens in 115 lines]... DONE in 27ms (0 errors, 0 warnings)
Processing ProcessorInterface.php [PHP => 168 tokens in 36 lines]... DONE in 21ms (0 errors, 0 warnings)
Changing into directory /Users/pascal/devel/csv-parser/tests
Processing ParserTest.php [PHP => 1797 tokens in 214 lines]... DONE in 149ms (0 errors, 0 warnings)
Processing TestProcessor.php [PHP => 427 tokens in 80 lines]... DONE in 31ms (0 errors, 0 warnings)
Processing ValidatorTest.php [PHP => 179 tokens in 33 lines]... DONE in 14ms (0 errors, 0 warnings)
Processing StreamTest.php [PHP => 1647 tokens in 217 lines]... DONE in 124ms (0 errors, 0 warnings)
Processing InvalidStream.php [PHP => 999 tokens in 210 lines]... DONE in 57ms (0 errors, 0 warnings)

```

**PHPUnit**

```
$ ./vendor/bin/phpunit
PHPUnit 7.4.0 by Sebastian Bergmann and contributors.

......................................                            38 / 38 (100%)

Time: 1.71 seconds, Memory: 8.00MB

OK (38 tests, 66 assertions)

Generating code coverage report in HTML format ... done

Code Coverage Report:
  2018-10-14 08:42:12

 Summary:
  Classes: 100.00% (3/3)
  Methods: 100.00% (36/36)
  Lines:   100.00% (150/150)

\Offdev\Csv::Offdev\Csv\Parser
  Methods: 100.00% (15/15)   Lines: 100.00% ( 76/ 76)
\Offdev\Csv::Offdev\Csv\Stream
  Methods: 100.00% (19/19)   Lines: 100.00% ( 67/ 67)
\Offdev\Csv::Offdev\Csv\Validator
  Methods: 100.00% ( 2/ 2)   Lines: 100.00% (  7/  7)

```

**Infection**

```
$ ./vendor/bin/infection
You are running Infection with xdebug enabled.
    ____      ____          __  _
   /  _/___  / __/__  _____/ /_(_)___  ____
   / // __ \/ /_/ _ \/ ___/ __/ / __ \/ __ \
 _/ // / / / __/  __/ /__/ /_/ / /_/ / / / /
/___/_/ /_/_/  \___/\___/\__/_/\____/_/ /_/

Running initial test suite...

PHPUnit version: 7.4.0

   44 [============================] 2 secsProcessing source code files: 0/5

Generate mutants...

Processing source code files: 5/5
Creating mutated files and processes: 89/89
.: killed, M: escaped, S: uncovered, E: fatal error, T: timed out

E.E...M..EEEM.EE.EEE.E.......E....................   (50 / 89)
...........E...........................              (89 / 89)

89 mutations were generated:
      74 mutants were killed
       0 mutants were not covered by tests
       2 covered mutants were not detected
      13 errors were encountered
       0 time outs were encountered

Metrics:
         Mutation Score Indicator (MSI): 97%
         Mutation Code Coverage: 100%
         Covered Code MSI: 97%

Please note that some mutants will inevitably be harmless (i.e. false positives).
Dashboard report has not been sent: it is not a Travis CI

Time: 17s. Memory: 14.00MB

```

### License

[](#license)

[Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0)

###  Health Score

35

—

LowBetter than 79% of packages

Maintenance26

Infrequent updates — may be unmaintained

Popularity27

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~26 days

Recently: every ~39 days

Total

7

Last Release

2612d ago

PHP version history (2 changes)1.0.0PHP &gt;=7.1

1.0.1PHP &gt;=7.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/49cd7805c119ee766fe6f126551fbf2e03c6145c038a7d89ec007b0a019dd809?d=identicon)[offdev](/maintainers/offdev)

---

Top Contributors

[![offdev](https://avatars.githubusercontent.com/u/7830782?v=4)](https://github.com/offdev "offdev (25 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/offdev-csv/health.svg)

```
[![Health](https://phpackages.com/badges/offdev-csv/health.svg)](https://phpackages.com/packages/offdev-csv)
```

###  Alternatives

[laravel/ui

Laravel UI utilities and presets.

2.7k134.9M601](/packages/laravel-ui)[spatie/laravel-honeypot

Preventing spam submitted through forms

1.6k6.0M60](/packages/spatie-laravel-honeypot)[watson/validating

Eloquent model validating trait.

9723.3M47](/packages/watson-validating)[stechstudio/laravel-zipstream

A fast and simple streaming zip file downloader for Laravel.

4633.7M3](/packages/stechstudio-laravel-zipstream)[axlon/laravel-postal-code-validation

Worldwide postal code validation for Laravel and Lumen

3853.3M1](/packages/axlon-laravel-postal-code-validation)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
