note 82050 added to function.split

From: Date: Tue, 25 Mar 2008 23:32:10 +0000
Subject: note 82050 added to function.split
Groups: php.notes 
Request: Send a blank email to php-notes+get-137582@lists.php.net to get a copy of this message
Those of you trying to use split for CSV, it won't always work as expected. Instead, try using a simple stack method: <?php /** * Create a 2D array from a CSV string * * @param mixed $data 2D array * @param string $delimiter Field delimiter * @param string $enclosure Field enclosure * @param string $newline Line seperator * @return */ function parse($data, $delimiter = ',', $enclosure = '"', $newline = "\n"){ $pos = $last_pos = -1; $end = strlen($data); $row = 0; $quote_open = false; $trim_quote = false; $return = array(); // Create a continuous loop for ($i = -1;; ++$i){ ++$pos; // Get the positions $comma_pos = strpos($data, $delimiter, $pos); $quote_pos = strpos($data, $enclosure, $pos); $newline_pos = strpos($data, $newline, $pos); // Which one comes first? $pos = min(($comma_pos === false) ? $end : $comma_pos, ($quote_pos === false) ? $end : $quote_pos, ($newline_pos === false) ? $end : $newline_pos); // Cache it $char = (isset($data[$pos])) ? $data[$pos] : null; $done = ($pos == $end); // It it a special character? if ($done || $char == $delimiter || $char == $newline){ // Ignore it as we're still in a quote if ($quote_open && !$done){ continue; } $length = $pos - ++$last_pos; // Is the last thing a quote? if ($trim_quote){ // Well then get rid of it --$length; } // Get all the contents of this column $return[$row][] = ($length > 0) ? str_replace($enclosure . $enclosure, $enclosure, substr($data, $last_pos, $length)) : ''; // And we're done if ($done){ break; } // Save the last position $last_pos = $pos; // Next row? if ($char == $newline){ ++$row; } $trim_quote = false; } // Our quote? else if ($char == $enclosure){ // Toggle it if ($quote_open == false){ // It's an opening quote $quote_open = true; $trim_quote = false; // Trim this opening quote? if ($last_pos + 1 == $pos){ ++$last_pos; } } else { // It's a closing quote $quote_open = false; // Trim the last quote? $trim_quote = true; } } } return $return; } ?> This *should* work for any valid CSV string, regardless of what it contains inside its quotes (using RFC 4180). It should also be faster than most of the others I've seen. It's very simple in concept, and thoroughly commented. ---- Server IP: 69.147.83.197 Probable Submitter: 81.140.40.33 ---- Manual Page -- http://www.php.net/manual/en/function.split.php Edit -- https://master.php.net/note/edit/82050 Del: integrated -- https://master.php.net/note/delete/82050/integrated Del: useless -- https://master.php.net/note/delete/82050/useless Del: bad code -- https://master.php.net/note/delete/82050/bad+code Del: spam -- https://master.php.net/note/delete/82050/spam Del: non-english -- https://master.php.net/note/delete/82050/non-english Del: in docs -- https://master.php.net/note/delete/82050/in+docs Del: other reasons-- https://master.php.net/note/delete/82050 Reject -- https://master.php.net/note/reject/82050 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#137582) next »