(PHP) tsvファイル 処理用簡易パッケージ

tsvファイル を機械的に処理したくなったので、自分用の簡易パッケージを作成しました。サクッと済ませたかったので全体的にガバガバですが……。

経緯

最初は

csv を処理するパッケージを使ってサクッと実装しようとした

……のですが、何故か結果が空配列となってしまい一向に進まなかったので自前で記述することに……。

コード

<?php

declare(strict_types=1);

namespace PhpTsvParser;

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

use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Exception;

date_default_timezone_set('Asia/Tokyo');

class PhpTsvParser
{
    protected Logger $logger;

    protected string $err_msg = 'データファイル読み込みでエラーが発生しました。';

    protected string $filepath;

    protected int $array_length;

    protected string $linefeed;

    protected string $separator;

    protected string $charset_from;

    protected string $charset_to;

    protected string $data;

    /**
     * @param string $filepath
     * @param snt    $array_length
     * @param string $separator
     * @param string $charset_from
     * @param string $charset_to
     */
    public function __construct(string $filepath, int $array_length, string $linefeed = "\n",string $separator = "\t", string $charset_from = 'UTF-8', string $charset_to = 'UTF-8')
    {
        $this->logger = new Logger('PhpTsvParser');
        $this->logger->pushHandler(new StreamHandler(__DIR__ . '/../logs/app.log', Logger::WARNING));

        $this->filepath = $filepath;
        $this->array_length = $array_length;
        $this->linefeed = $linefeed;
        $this->separator = $separator;
        $this->charset_from = $charset_from;
        $this->charset_to = $charset_to;
    }

    /**
     * @return array
     */
    public function read(): array
    {
        if(
            !file_exists($this->filepath)
            || file_get_contents($this->filepath) === false
        ) {
            $this->logger->error(
                $this->err_msg,
                [
                    'filepath' => $this->filepath,
                ]
            );
            throw new Exception($this->err_msg);
        }
        // データ文字列から改行文字で配列へ
        $dataArr = explode($this->linefeed, file_get_contents($this->filepath));
        // 結果の配列を用意
        $resultArr = [];
        // ループ
        for($i = 0; $i < count($dataArr); ++$i ){
            // 文字コード
            $elm = nl2br(
                mb_convert_encoding(
                    $dataArr[$i],
                    $this->charset_to,
                    $this->charset_from
                )
            );
            // 行が空文字列ならば指定要素数の空文字列の配列を生成、そうでなければ指定区切り文字列で分解した要素の配列を生成
            $elmArr = $elm === '' ?  array_fill(0, $this->array_length, '') : explode($this->separator, $elm);

            $resultArr[] = $elmArr;
        }
        return $resultArr;
    }
}

最初は fgetcsv を利用しようかと思ったのですが、これも文字コードの絡み等を考えて没に。

結局 file_get_contents() + explode() という形に落ち着きました。

その性質上、大量のデータを処理することは想定していないです。せいぜい 300 x 20 くらいのサイズ感で考えています。

後は最低限ですが monolog を使っているくらいですかね。

参考

mb_convert_encoding()

explode()

file_get_contents()

array_fill()

Github 上の自作パッケージを Composer で読む

Monolog

PHPUnit

(未使用) parsecsv/php-parsecsv

(未使用) fgetcsv()

(未使用) fopen()

この記事を書いた人

アルム=バンド

フロントエンド・バックエンド・サーバエンジニア。LAMPやNodeからWP、Gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。