目次
TSV と CSV を読み込むコードを書きました。
RAILS 4 : TSV, CSV から SEED データ を入れる に書いた方法を PHP に合わせてアレンジしたものです。
TSV と CSV に関するクラスを作る
まずは CSV と TSV を現すクラスと、ファクトリーのクラスを作ります。 (ファクトリーについてはJava言語で学ぶデザインパターン入門をご参照ください。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
<?php class Xsv implements Iterator { /** * @var xsv file name */ protected $filePath; /** * @var field separator */ protected $separator; protected $fileHandler; protected $line; protected $values; protected $columns; protected $key; function __construct($filePath, $separator) { $this->filePath = $filePath; $this->separator = $separator; $this->fileHandler = fopen($filePath, "r"); $this->rewind($this->fileHandler); } function __destruct() { fclose($this->fileHandler); } protected function readAndSetLine() { if (FALSE == ($line = fgets($this->fileHandler))) { if (!feof($this->fileHandler)) { throw new Exception("file read exception!"); } return $this->line = null; } return $this->line = rtrim($line); } protected function setValues(array $items) { $this->values = array(); foreach ($this->columns as $key => $column) { $this->values[$column] = $items[$key]; } } function current() { return $this->line == FALSE ? null : $this->values; } function key() { return $this->key; } function next() { if ($this->readAndSetLine() == null) { // end of file $this->key = null; $this->values = null; return; } $items = explode($this->separator, $this->line); if ($this->columns == null) { $this->columns = $items; $this->key = 0; return; } $this->setValues($items); ++$this->key; } function rewind() { rewind($this->fileHandler); $this->columns = null; $this->key = null; $this->next(); $this->next(); } function valid() { return $this->line !== null; } } class Tsv extends Xsv { function __construct($filePath) { parent::__construct($filePath, "t"); } } class Csv extends Xsv { function __construct($filePath) { parent::__construct($filePath, ","); } } class XsvFactory { static function createXsv($filePath) { switch (strtolower(substr($filePath, -3))) { case "csv": return new Csv($filePath); case "tsv": return new Tsv($filePath); default: throw new Exception("File format is invalid ${$filePath}."); } } } |
今回は yield
を使いませんでした、 古いバージョンの PHP でも実行できるように。
Xsv
クラス は FileIterator
を作ってそれを継承するように作った方がよかったですね。
注意
TSV と CSV の 1行目はカラム名にして、 データは2行目から記述してください。 最後の行の行末では改行しないようにしてください。
使い方
次のようなコードで、データの番号とデータを取り出すことができます。
1 2 3 4 5 |
$xsv = XsvFactory::createXsv($filePath); foreach ($xsv as $dataNumber => $items) { // you can do whatever } |
$items
の構造は次のようになります。
1 2 3 4 5 |
$items = array( 'column_name_1' => 'value_1', 'column_name_2' => 'value_2', 'column_name_3' => 'value_3' ); |
そして、フィールドのデータは $item['column_name_1']
のように取得することができます。