offdev/csv

使用流读取、解析和验证CSV文件

1.2.2 2019-03-21 14:50 UTC

This package is auto-updated.

Last update: 2024-09-22 08:43:58 UTC


README

Latest Stable Version Minimum PHP Version Build Status PHPStan Mutation Score License

需求

  • PHP >= 7.2
  • Composer

安装

$ composer require offdev/csv

介绍

这个解析器被编写出来,以便以简单方便的方式解析来自几乎任何数据源的大CSV文件。它还提供了验证CSV源中每个记录的可能性。

为了让解析器工作,您需要向其提供数据。这些数据将以流的形式表示。这使我们能够处理大量数据。解析器还可以处理HTTP流。

请继续阅读以了解其使用方法。

为了向解析器提供数据,您需要给它一个流。流可以通过多种方式获得

使用资源

use Offdev\Csv\Stream;

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

使用字符串

use Offdev\Csv\Stream;

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

注意:此方法也适用于实现了 __toString 方法的任何对象。

使用HTTP流(参见 PSR-7/Streams

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

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

便利性

如果您想快速创建一个流,可以使用提供的辅助函数。您需要使用composer的自动加载器才能使用此功能。

// 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());

解析器

基础知识

一旦解析器有一个流可以工作,我们就可以开始使用它

use Offdev\Csv\Parser;

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

上面的示例生成了以下输出

$ php example.php
row1-value2
row2-value2

为了方便,解析器也可以用作迭代器

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

这将产生与上面示例相同的输出。

选项

解析器接受许多选项。解析器接受数组中的选项,该数组作为构造函数的第二个参数传递

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

选项完整列表

处理器

为了提高可用性和关注点的分离,解析器接受一个处理器,该处理器将接收来自流的任何解析记录。记录表示为 Laravel 集合

如果为解析器分配了验证器,则有效和无效的记录将传递到相应的方法。如果没有提供验证器,则所有记录都将传递到 parseRecord 方法。空行始终被忽略。

示例处理器

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;
    }
}

用法

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();

上面的示例生成了以下输出

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

验证器

现在,大多数时候,我们希望确保CSV中包含的数据符合给定的格式。此软件包使用Laravel验证软件包来为CSV的内容提供规则引擎。所有规则的全列表可以在此找到。

用法

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;
}

代码质量

首先,通过运行 composer install 安装依赖项。您还需要确保启用xdebug,以便PHPUnit生成代码覆盖率。

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

许可证

Apache-2.0