147 lines
4.3 KiB
PHP
147 lines
4.3 KiB
PHP
<?php
|
|
require_once(__DIR__.'/ArrayExtended.php');
|
|
class CSVReader
|
|
{
|
|
private $file_path = '';
|
|
private $params = array('enable_skip_line' => false, 'auto_detect'=>true, 'separator' => ',', 'enclosure' => '"', 'expected_header' => array());
|
|
private $handlers = array('start' => null, 'error' => null);
|
|
private $current_num_line = 0;
|
|
private $expected_cols_index = array();
|
|
|
|
function __construct($file_path)
|
|
{
|
|
$this->file_path = $file_path;
|
|
$this->handlers = array(
|
|
'start' => function() {},
|
|
'error' => function($failed_line_number) {},
|
|
'readline' => function(ArrayExtended $cols) { return true; }
|
|
);
|
|
|
|
// if required, convert the file to the correct format
|
|
$str = file_get_contents($file_path);
|
|
if (mb_detect_encoding($str, "UTF-8,ISO-8859-1", true) == 'ISO-8859-1') {
|
|
file_put_contents($file_path, utf8_encode(file_get_contents($file_path)));
|
|
}
|
|
}
|
|
|
|
function setExpectedHeader(array $expected_header)
|
|
{
|
|
$this->params['expected_header'] = $expected_header;
|
|
return $this;
|
|
}
|
|
|
|
function enableSkipHeader()
|
|
{
|
|
$this->params['enable_skip_line'] = true;
|
|
return $this;
|
|
}
|
|
|
|
// func : function()
|
|
function setOnStart(callable $func)
|
|
{
|
|
$this->handlers['start'] = $func;
|
|
return $this;
|
|
}
|
|
|
|
// func : function(ArrayExtended $columns)
|
|
function setOnEachLine(callable $func)
|
|
{
|
|
$this->handlers['readline'] = $func;
|
|
return $this;
|
|
}
|
|
|
|
// func : function(int failed_line_number)
|
|
function setOnError(callable $func)
|
|
{
|
|
$this->handlers['error'] = $func;
|
|
return $this;
|
|
}
|
|
|
|
function readLines()
|
|
{
|
|
$ok = false;
|
|
$this->current_num_line = 0;
|
|
|
|
if ($this->params['auto_detect']) {
|
|
$this->autoDetect($this->file_path);
|
|
}
|
|
|
|
$f = fopen($this->file_path, 'r');
|
|
if ($f) {
|
|
call_user_func($this->handlers['start']);
|
|
|
|
$ok = true;
|
|
if ($this->params['enable_skip_line'] || count($this->params['expected_header'])>0) {
|
|
$ok = $this->checkHeader(fgetcsv($f, 0, $this->params['separator'], $this->params['enclosure']));
|
|
}
|
|
|
|
while ($ok && ($cols = fgetcsv($f, 0, $this->params['separator'], $this->params['enclosure']))) {
|
|
$real_cols = array();
|
|
|
|
foreach($this->expected_cols_index as $real_index => $index) {
|
|
$real_cols[$index] = trim($cols[$real_index]);
|
|
}
|
|
$ok = call_user_func($this->handlers['readline'], new ArrayExtended($real_cols));
|
|
$this->current_num_line++;
|
|
}
|
|
|
|
fclose($f);
|
|
}
|
|
|
|
if (!$ok) {
|
|
call_user_func($this->handlers['error'], $this->current_num_line);
|
|
}
|
|
|
|
return $ok;
|
|
}
|
|
|
|
private function checkHeader(array $cols)
|
|
{
|
|
$ok = true;
|
|
|
|
foreach($this->params['expected_header'] as $expected_col => $expected_pos) {
|
|
$found = false;
|
|
foreach($cols as $index => $col) {
|
|
if (strtolower($col) == strtolower($expected_col)) {
|
|
$this->expected_cols_index[$index] = $expected_pos;
|
|
$found = true;
|
|
break;
|
|
}
|
|
}
|
|
$ok = $ok && $found;
|
|
}
|
|
|
|
return $ok;
|
|
}
|
|
|
|
private function autoDetect($file_path)
|
|
{
|
|
if ($f = fopen($file_path, 'r')) {
|
|
$line = fgets($f);
|
|
|
|
if ($line[0] == '"') {
|
|
$line[0] = '';
|
|
$line = str_replace("\\\"", '', $line);
|
|
$line = str_replace("\"\"", '', $line);
|
|
$line = strstr($line, '"');
|
|
if (strlen($line)>1) {
|
|
$this->params['separator'] = $line[1];
|
|
}
|
|
}
|
|
else {
|
|
if (strpos($line, ';')!==false) {
|
|
$this->params['separator'] = ';';
|
|
}
|
|
elseif (strpos($line, ',')!==false) {
|
|
$this->params['separator'] = ',';
|
|
}
|
|
elseif (strpos($line, '|')!==false) {
|
|
$this->params['separator'] = '|';
|
|
}
|
|
}
|
|
|
|
fclose($f);
|
|
}
|
|
}
|
|
}
|