123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- <?php
- /**
- * CSVParser
- * CSV interpreter helper, optionaly tries to guess column mapping and the separator, check the consistency
- *
- * @package iTopORM
- * @author Romain Quetiez <romainquetiez@yahoo.fr>
- * @author Denis Flaven <denisflave@free.fr>
- * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
- * @link www.itop.com
- * @since 1.0
- * @version 1.1.1.1 $
- */
- class CSVParserException extends CoreException
- {
- }
- /**
- * CSVParser
- *
- * @package iTopORM
- * @author Romain Quetiez <romainquetiez@yahoo.fr>
- * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
- * @link www.itop.com
- * @since 1.0
- * @version $itopversion$
- */
- class CSVParser
- {
- private $m_sCSVData;
- private $m_sSep;
- private $m_iSkip;
- public function __construct($sTxt)
- {
- $this->m_sCSVData = $sTxt;
- }
- public function SetSeparator($sSep)
- {
- $this->m_sSep = $sSep;
- }
- public function GetSeparator()
- {
- return $this->m_sSep;
- }
- public function SetSkipLines($iSkip)
- {
- $this->m_iSkip = $iSkip;
- }
- public function GetSkipLines()
- {
- return $this->m_iSkip;
- }
- public function GuessSeparator()
- {
- // Note: skip the first line anyway
-
- $aKnownSeps = array(';', ',', "\t"); // Use double quote for special chars!!!
- $aStatsBySeparator = array();
- foreach ($aKnownSeps as $sSep)
- {
- $aStatsBySeparator[$sSep] = array();
- }
-
- foreach(explode("\n", $this->m_sCSVData) as $sLine)
- {
- $sLine = trim($sLine);
- if (substr($sLine, 0, 1) == '#') continue;
- if (empty($sLine)) continue;
-
- $aLineCharsCount = count_chars($sLine, 0);
- foreach ($aKnownSeps as $sSep)
- {
- $aStatsBySeparator[$sSep][] = $aLineCharsCount[ord($sSep)];
- }
- }
-
- // Default to ','
- $this->SetSeparator(",");
- foreach ($aKnownSeps as $sSep)
- {
- // Note: this function is NOT available :-(
- // stats_variance($aStatsBySeparator[$sSep]);
- $iMin = min($aStatsBySeparator[$sSep]);
- $iMax = max($aStatsBySeparator[$sSep]);
- if (($iMin == $iMax) && ($iMax > 0))
- {
- $this->SetSeparator($sSep);
- break;
- }
- }
- return $this->GetSeparator();
- }
- public function GuessSkipLines()
- {
- // Take the FIRST -valuable- LINE ONLY
- // If there is a number, then for sure this is not a header line
- // Otherwise, we may consider that there is one line to skip
- foreach(explode("\n", $this->m_sCSVData) as $sLine)
- {
- $sLine = trim($sLine);
- if (substr($sLine, 0, 1) == '#') continue;
- if (empty($sLine)) continue;
-
- foreach (explode($this->m_sSep, $sLine) as $value)
- {
- if (is_numeric($value))
- {
- $this->SetSkipLines(0);
- return 0;
- }
- }
- $this->SetSkipLines(1);
- return 1;
- }
- }
- function ToArray($aFieldMap = null, $iMax = 0)
- {
- // $aFieldMap is an array of col_index=>col_name
- // $iMax is to limit the count of rows computed
- $aRes = array();
-
- $iCount = 0;
- $iSkipped = 0;
- foreach(explode("\n", $this->m_sCSVData) as $sLine)
- {
- $sLine = trim($sLine);
- if (substr($sLine, 0, 1) == '#') continue;
- if (empty($sLine)) continue;
-
- if ($iSkipped < $this->m_iSkip)
- {
- $iSkipped++;
- continue;
- }
-
- foreach (explode($this->m_sSep, $sLine) as $iCol=>$sValue)
- {
- if (is_array($aFieldMap)) $sColRef = $aFieldMap[$iCol];
- else $sColRef = $iCol;
- $aRes[$iCount][$sColRef] = $sValue;
- }
-
- $iCount++;
- if (($iMax > 0) && ($iCount >= $iMax)) break;
- }
- return $aRes;
- }
- public function ListFields()
- {
- // Take the first valuable line
- foreach(explode("\n", $this->m_sCSVData) as $sLine)
- {
- $sLine = trim($sLine);
- if (substr($sLine, 0, 1) == '#') continue;
- if (empty($sLine)) continue;
- // We've got the first valuable line, that's it!
- break;
- }
- $aRet = array();
- foreach (explode($this->m_sSep, $sLine) as $iCol=>$value)
- {
- if ($this->m_iSkip == 0)
- {
- // No header to help us
- $sLabel = "field $iCol";
- }
- else
- {
- $sLabel = "$value";
- }
- $aRet[] = $sLabel;
- }
- return $aRet;
- }
- }
- ?>
|