PHP 使用 file

PHPCSV教程展示了如何在PHP中处理CSV数据。

$ php -v
php -v
PHP 8.1.2 (cli) (built: Aug  8 2022 07:28:23) (NTS)
...

我们使用PHP版本8.1.2。

CSV

CSV(逗号分隔值)是一种非常流行的导入和导出数据格式,用于电子表格和数据库。CSV文件中的每一行都是一条数据记录。每条记录由一个或多个字段组成,以逗号分隔。虽然CSV是一种非常简单的数据格式,但可能存在许多差异,例如不同的分隔符、换行符或引号字符。

fgetcsv从提供的文件指针中读取一行并解析CSV字段。它返回一个包含读取字段的数组。fputcsv获取一组数据并将其作为CSV行写入指定的文件句柄。

league/csv是一个简单的PHP库,用于简化CSV文件的加载以及编写、选择和转换CSV记录。

PHP使用fgetcsv读取CSV

以下示例使用内置的fgetcsv函数读取CSV数据。

John,Doe,gardener
Lucy,Smith,teacher
Brian,Bethamy,programmer

这是users.csv文件。

<?php

$f = fopen('users.csv', 'r');

while(!feof($f)) {

    $row = fgetcsv($f);

    if (!empty($row)) {
          echo "$row[0] $row[1] is a(n) $row[2]\n";
    }
}

fclose($f);

我们从users.csv文件中读取数据。

$f = fopen('users.csv', 'r');

使用fopen,我们打开users.csv文件的文件句柄。

while(!feof($f)) {

在while循环中,我们读取所有行直到文件末尾。feof函数检查文件句柄上的文件结尾。

$row = fgetcsv($f);

我们用fgetcsv读取了一行;该函数返回读取的字段数组。

if (!empty($row)) {
    echo "$row[0] $row[1] is a(n) $row[2]\n";
}

如果该行不为空,我们将在消息中输出字段。

fclose($f);

fclose函数关闭打开的文件指针。

$ php read_data.php
John Doe is a(n) gardener
Lucy Smith is a(n) teacher
Brian Bethamy is a(n) programmer

PHP用fputcsv写CSV

以下示例将CSV数据写入文件。

<?php

$users = [
    ['John', 'Doe', 'gardener' ],
    ['Lucy', 'Smith', 'teacher'],
    ['Brian', 'Bethamy', 'programmer']
];

$fp = fopen('users.csv', 'w');

foreach ($users as $user) {
    fputcsv($fp, $user);
}

fclose($fp);

我们有很多用户。我们使用fputcsv将用户写入CSV文件。

PHPCSV不同分隔符

fgetcsv函数允许使用不同的分隔符读取数据。

John|Doe|gardener
Lucy|Smith|teacher
Brian|Bethamy|programmer

我们用|字符分隔数据。

<?php

$f = fopen('users2.csv', 'r');

while(!feof($f)) {

    $row = fgetcsv($f, 0, '|');

    if (!empty($row)) {
          echo "$row[0] $row[1] is a(n) $row[2]\n";
    }
}

fclose($f);

fgetcsv函数的第三个参数是optionaldelimiter,设置字段分隔符(一个字符)。默认为逗号。

PHP发送CSV数据

以下示例将CSV数据作为附件发送给用户。

<?php

header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=users.csv');

$output = fopen('php://output', 'w');

fputcsv($output, ['First name', 'Last name', 'Occupation']);

$f = fopen('users.csv', 'r');

while (!feof($f)) {

    $rows[] = fgetcsv($f);
}

foreach ($rows as $row) {

    fputcsv($output, $row);
}

fclose($f);

该示例从文件中读取CSV并将其返回给用户;用户收到文件作为附件。

header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=users.csv');

这些标头指定内容类型和作为附件的处置。

$output = fopen('php://output', 'w');

我们创建一个连接到输出流的文件指针。

fputcsv($output, ['First name', 'Last name', 'Occupation']);

我们将标头字段发送到输出流。

$f = fopen('users.csv', 'r');

while (!feof($f)) {

    $rows[] = fgetcsv($f);
}

我们将CSV数据读入数组。

foreach ($rows as $row) {

    fputcsv($output, $row);
}

数组被写入输出流。

PHP联赛\csv

league\csv是一个用于处理CSV数据的PHP库。

$ composer require league/csv

库是用上面的命令安装的。

首先我们用League\Csv\Reader解析CSV数据进行读取。League\Csv\Statement类是一个约束生成器,用于从League\Csv\Reader创建的CSV文档中选择记录。Statement::process方法处理读取器对象并将找到的记录作为ResultSet对象返回。我们可以像在SQL中一样对结果集执行过滤、间隔或排序操作。

我们使用League\Csv\Writer进行写作。

'First name','Last name','Occupation'
John,Doe,gardener
Lucy,Smith,teacher
Brian,Bethamy,programmer
Lucy,Black,musician
Pau,Novak,teacher

我们有这些数据。

PHP联盟\csv计数行

在第一个示例中,我们计算CSV文件中的可用行数。

<?php

require __DIR__ . '/vendor/autoload.php';

use League\Csv\Reader;
use League\Csv\Statement;

$reader = Reader::createFromPath('users.csv', 'r');
$rows = Statement::create()->process($reader);
echo count($rows);

我们使用Reader::createFromPath创建一个阅读器对象。然后我们创建一个语句并使用process方法处理读取器对象。对返回的结果集应用count函数返回行数。

$ php count_rows.php
6

文件中有六行,包括标题。

如果我们不想要标题行,我们可以使用setHeaderOffset

<?php

require __DIR__ . '/vendor/autoload.php';

use League\Csv\Reader;
use League\Csv\Statement;

$reader = Reader::createFromPath('users.csv', 'r');
$reader->setHeaderOffset(0);

$rows = Statement::create()->process($reader);
echo count($rows);

我们计算CSV文件中的行数,不包括标题行。

PHP联盟\csv读取数据

在下面的示例中,我们使用league\csv读取CSV数据。

<?php

require __DIR__ . '/vendor/autoload.php';

use League\Csv\Reader;

$csv = Reader::createFromPath('users.csv', 'r');
$csv->setHeaderOffset(0);

$header = $csv->getHeader();
print_r($header);

$records = $csv->getRecords();
print_r(iterator_to_array($records));

echo $csv->getContent();

我们从users.csv文件中读取标题和数据。

$csv = Reader::createFromPath('users.csv', 'r');
$csv->setHeaderOffset(0);

我们创建阅读器对象并设置标题位置。

$header = $csv->getHeader();
print_r($header);

我们得到标题行。

$records = $csv->getRecords();
print_r(iterator_to_array($records));

getRecords方法将所有CSV记录作为Iterator对象返回。

echo $csv->getContent();

getContent方法将CSV文档作为字符串返回。

$ php read_data2.php
Array
(
    [0] => 'First name'
    [1] => 'Last name'
    [2] => 'Occupation'
)
Array
(
    [1] => Array
        (
            ['First name'] => John
            ['Last name'] => Doe
            ['Occupation'] => gardener
        )

    [2] => Array
        (
            ['First name'] => Lucy
            ['Last name'] => Smith
            ['Occupation'] => teacher
        )

    [3] => Array
        (
            ['First name'] => Brian
            ['Last name'] => Bethamy
            ['Occupation'] => programmer
        )

    [4] => Array
        (
            ['First name'] => Lucy
            ['Last name'] => Black
            ['Occupation'] => musician
        )

    [5] => Array
        (
            ['First name'] => Pau
            ['Last name'] => Novak
            ['Occupation'] => teacher
        )

)
'First name','Last name','Occupation'
John,Doe,gardener
Lucy,Smith,teacher
Brian,Bethamy,programmer
Lucy,Black,musician
Pau,Novak,teacher

PHP联盟/csvfetchColumn

可以使用fetchColumn选择特定的数据列。

<?php

require __DIR__ . '/vendor/autoload.php';

use League\Csv\Reader;
use League\Csv\Statement;

$reader = Reader::createFromPath('users.csv', 'r');
$reader->setHeaderOffset(0);

$records = Statement::create()->process($reader);

foreach ($records->fetchColumn(2) as $value) {
    echo $value . "\n";
}

在示例中,我们从数据中获取第三列。

$ php fetch_column.php
gardener
teacher
programmer
musician
teacher

Slim中的PHPCSV

在下面的示例中,我们从Slim应用程序返回CSV数据。

$ composer req slim/slim
$ composer req slim/psr7
$ composer req slim/http

我们安装了slim/slimslim/psr7slim/http包。

<?php

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
use Slim\Psr7\Stream;

require __DIR__ . '/../vendor/autoload.php';

$app = AppFactory::create();

$app->get('/users', function (Request $request, Response $response): Response {

    $csv_file = '../users.csv';
    $fp = fopen($csv_file);
    $stream = new Stream(fopen($csv_file, 'rb'));

    return $response->withHeader('Content-Type', 'application/octet-stream')
        ->withHeader('Content-Disposition', 'attachment; filename=users.csv')
        ->withHeader('Pragma', 'no-cache')
        ->withBody($stream);
});

$app->run();

我们从文件中读取数据并将其发送到响应正文中。

$ php -S localhost:8000 -t public

我们启动内置服务器。

$ curl localhost:8000/users
"First name","Last name",Occupation
John,Doe,gardener
Lucy,Smith,teacher
Brian,Bethamy,programmer

GET请求是使用curl创建的。

Symfony中的PHPCSV

在以下示例中,我们从Symfony应用程序发送CSV响应。

$ symfony new symcsv
$ cd symcsv

创建了一个新项目。

$ composer req maker --dev
$ composer req annot

我们安装了makerannot依赖项。

$ php bin/console make:controller UserController

我们创建了UserController

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use App\Service\ContainerParametersHelper;

class UserController extends AbstractController
{
    /**
     * @Route("/users", name="user")
     */
    public function index(): Response
    {
        $rootDir = $this->getParameter('kernel.project_dir');

        $fp = fopen("$rootDir/var/users.csv", 'r');
        $response = new Response(stream_get_contents($fp));
        fclose($fp);

        $response->headers->set('Content-Type', 'text/csv');
        $response->headers->set('Pragma', 'no-cache');
        $response->headers->set('Content-Disposition',
            'attachment; filename="users.csv"');

        return $response;
    }
}

users.csv文件位于var目录中。我们读取文件的内容并将其作为附件发送到响应对象中。

$ symfony serve

我们启动网络服务器。

$ curl localhost:8000/users
"First name","Last name",Occupation
John,Doe,gardener
Lucy,Smith,teacher
Brian,Bethamy,programmer

我们使用curl发送GET请求。

Laravel中的PHPCSV

在以下示例中,我们从Laravel应用程序发送CSV响应。

$ laravel new laracsv
$ cd laracsv

创建了一个新项目。

<?php

use Illuminate\Support\Facades\Route;
use Symfony\Component\HttpFoundation\StreamedResponse;

Route::get('/users', function() : StreamedResponse {

    $headers = [
        "Content-type"        => "text/csv",
        "Content-Disposition" => "attachment; filename=users.csv",
        "Pragma"              => "no-cache",
    ];

    $columns = ['First name', 'Last name', 'Occupation'];
    $fileName = storage_path('users.csv');
    $f = fopen($fileName, 'r');

    while (!feof($f)) {

        $rows[] = fgetcsv($f);
    }

    fclose($f);

    return new StreamedResponse(

        function() use ($rows) {

            $handle = fopen('php://output', 'w');

            foreach ($rows as $row) {

                if (!empty($row)) {
                    fputcsv($handle, $row);
                }
            }

            fclose($handle);
        },
        200,
        [
            'Content-type'        => 'text/csv',
            'Content-Disposition' => 'attachment; filename=members.csv'
        ]
    );
});

users.csv文件位于storage目录中。我们读取文件的内容并将其作为附件发送到响应对象中。

$ php artisan serve

我们启动Web服务器并定位到localhost:8000/users

在本教程中,我们在纯PHP、Symfony、Slim和Laravel中处理了CSV数据。

列出所有PHP教程。

赞(0) 打赏

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏