Location: PHPKode > scripts > PHP-CSV > php-csv-master/csv.php
<?php

class Csv {
	// take a CSV line (utf-8 encoded) and returns an array
	// 'string1,string2,"string3","the ""string4"""' => array('string1', 'string2', 'string3', 'the "string4"')
	static public function parseString($string, $separator = ',') {
		$values = array();
		$string = str_replace("\r\n", '', $string); // eat the traling new line, if any
		if ($string == '') return $values;
		$tokens = explode($separator, $string);
		$count = count($tokens);
		for ($i = 0; $i < $count; $i++) {
			$token = $tokens[$i];
			$len = strlen($token);
			$newValue = '';
			if ($len > 0 and $token[0] == '"') { // if quoted
				$token = substr($token, 1); // remove leading quote
				do { // concatenate with next token while incomplete
					$complete = Csv::_hasEndQuote($token);
					$token = str_replace('""', '"', $token); // unescape escaped quotes
					$len = strlen($token);
					if ($complete) { // if complete
						$newValue .= substr($token, 0, -1); // remove trailing quote
					} else { // incomplete, get one more token
						$newValue .= $token;
						$newValue .= $separator;
						if ($i == $count - 1) throw new Exception('Illegal unescaped quote.');
						$token = $tokens[++$i];
					}
				} while (!$complete);

			} else { // unescaped, use token as is
				$newValue .= $token;
			}

			$values[] = $newValue;
		}
		return $values;
	}

	static public function escapeString($string) {
		$string = str_replace('"', '""', $string);
		if (strpos($string, '"') !== false or strpos($string, ',') !== false or strpos($string, "\r") !== false or strpos($string, "\n") !== false) {
			$string = '"'.$string.'"';
		}

		return $string;
	}

	// checks if a string ends with an unescaped quote
	// 'string"' => true
	// 'string""' => false
	// 'string"""' => true
	static public function _hasEndQuote($token) {
		$len = strlen($token);
		if ($len == 0) return false;
		elseif ($len == 1 and $token == '"') return true;
		elseif ($len > 1) {
			while ($len > 1 and $token[$len-1] == '"' and $token[$len-2] == '"') { // there is an escaped quote at the end
				$len -= 2; // strip the escaped quote at the end
			}
			if ($len == 0) return false; // the string was only some escaped quotes
			elseif ($token[$len-1] == '"') return true; // the last quote was not escaped
			else return false; // was not ending with an unescaped quote
		}
	}
	
	// very basic separator detection function
	static public function detectSeparator($filename, $separators = array(',', ';')) {
		$file = fopen($filename, 'r');
		$string = fgets($file);
		fclose($file);
		$matched = array();
		foreach ($separators as $separator) if (preg_match("/$separator/", $string)) $matched[] = $separator;
		if (count($matched) == 1) return $matched[0];
		else return null;
	}
}

class CsvReader implements Iterator {

	protected $fileHandle = null;
	protected $position = null;
	protected $filename = null;
	protected $currentLine = null;
	protected $currentArray = null;
	protected $separator = ',';
	

	public function __construct($filename, $separator = ',') {
		$this->separator = $separator;
		$this->fileHandle = fopen($filename, 'r');
		if (!$this->fileHandle) return;
		$this->filename = $filename;
		$this->position = 0;
		$this->_readLine();
	}

	public function __destruct() {
		$this->close();
	}

	// You should not have to call it unless you need to
	// explicitly free the file descriptor
	public function close() {
		if ($this->fileHandle) {
			fclose($this->fileHandle);
			$this->fileHandle = null;
		}
	}

	public function rewind() {
		if ($this->fileHandle) {
			$this->position = 0;
			rewind($this->fileHandle);
		}

		$this->_readLine();
	}

	public function current() {
		return $this->currentArray;
	}

	public function key() {
		return $this->position;
	}

	public function next() {
		$this->position++;
		$this->_readLine();
	}

	public function valid() {
		return $this->currentArray !== null;
	}

	protected function _readLine() {
		if (!feof($this->fileHandle)) $this->currentLine = trim(utf8_encode(fgets($this->fileHandle)));
		else $this->currentLine = null;
		if ($this->currentLine != '') $this->currentArray = Csv::parseString($this->currentLine, $this->separator);
		else $this->currentArray = null;
	}
}

class CsvWriter {

	protected $fileHandle = null;

	public function __construct($filename, $mode = 'w') {
		if ($mode != 'w' and $mode != 'a') throw new Exception('CsvWriter only accepts "w" and "a" mode.');
		$this->fileHandle = fopen($filename, $mode);
		if (!$this->fileHandle) throw new Exception("Impossible to open file $filename.");
	}

	public function __destruct() {
		$this->close();
	}

	public function addLine(array $values) {
		foreach ($values as $key => $value) {
			$values[$key] = utf8_decode(Csv::escapeString($value));
		}
		$string = implode(',', $values) . "\r\n";
		fwrite($this->fileHandle, $string);
	}

	// You should not have to call it unless you need to flush the
	// data from the buffer to your file explicitly before the
	// end of your script
	public function close() {
		if ($this->fileHandle) {
			fclose($this->fileHandle);
			$this->fileHandle = null;
		}
	}
}
Return current item: PHP-CSV