I wrote the code to handle TSV and CSV.
This method is really similar to RAILS 4 : Load Seed from TSV and CSV
Create TSV and CSV class
First, create classes which represent CSV and TSV, and Factory class.
|
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}."); } } } |
All right. In this time, I didn’t used yield method. So it can be used with old version PHP.
Well, I must have create FileIterator and create Xsv class which inherits FileIterator.
Attention
The first line of TSV and CSV should contain column names, and data start at second line. And at last line should ends without LF.
Usage
At the following code, you can get data number and its data.
|
1 2 3 4 5 |
$xsv = XsvFactory::createXsv($filePath); foreach ($xsv as $dataNumber => $items) { // you can do whatever } |
And, $items structure is like the following.
|
1 2 3 4 5 |
$items = array( 'column_name_1' => 'value_1', 'column_name_2' => 'value_2', 'column_name_3' => 'value_3' ); |
So you can get column data like $item['column_name_1'].