note 82637 deleted from function.fgetcsv by danbrown
| From: | danbrown@php.net | Date: | Sun, 17 May 2009 18:08:54 +0000 |
| Subject: | note 82637 deleted from function.fgetcsv by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-155068@lists.php.net to get a copy of this message | ||
Note Submitter: Philipp
----
With this modification the last item will be added to the array:
"a","b","c" is transformed to
array("a","b","c") - old function returned
array("a","b")
<?php
/*
Modified function from user comment by Marcos Boyington / 06-Mar-2008 03:08
This is a pretty useful update/modification to the fgetcsv function, which allows for:
* Multiple-character/multibyte delim/enclosure/escape
* Multibyte values
* Escape character specification in < PHP5
* Escape character = delim character
* Direct reading from files without bloating memory too much
*/
define('BUFFER_READ_LEN', 4096);
function fgetcsv_ex($file_handle, $delim = ',', $enclosure = '"', $escape =
'"') {
$fields = null;
$fldCount = 0;
$inQuotes = false;
$complete = false;
$search_chars_list = array('\r\n', '\n', '\r');
if ($delim && ($delim != ''))
$search_chars_list[] = $delim;
if ($enclosure && ($enclosure != '')) {
$search_chars_list[] = $enclosure;
$enclosure_len = strlen($enclosure);
} else
$enclosure_len = 0;
if ($escape && ($escape != '')) {
$search_chars_list[] = $escape;
$escape_len = strlen($escape);
} else
$escape_len = 0;
$search_regex = '/' . implode('|', $search_chars_list) . '/';
$cur_pos = 0;
$line = '';
$cur_value = '';
$in_value = false;
$last_value = 0;
while (! $complete) {
$read_result = fread($file_handle, BUFFER_READ_LEN);
if ($read_result) {
$line .= $read_result;
} else if (strlen($line) == 0) {
return null;
} else {
$line .= "\n";
}
$line_len = strlen($line);
while (true) {
if (! preg_match($search_regex, $line, $matches, PREG_OFFSET_CAPTURE, $cur_pos)) {
if ($read_result) {
// need more chars
break;
} else {
// Incomplete file
return null;
}
} else {
$non_escape = false;
$cur_char = $matches[0][0];
$cur_len = strlen($cur_char);
$new_pos = $matches[0][1];
if (($enclosure == $escape) && $in_value && ($cur_char == $escape)) {
// Escape char = enclosure char special handling
if (($new_pos + $cur_len + $enclosure_len) >= $line_len) {
// We need the next char
break;
}
$next_char = substr($line, $new_pos + $cur_len, $enclosure_len);
if ((! $enclosure) || ($next_char != $enclosure)) {
$non_escape = true;
}
}
$cur_pos = $new_pos;
if ($in_value && (! $non_escape)) {
$cur_value .= mb_substr($line, $last_value, $cur_pos - $last_value);
if ($cur_char == $escape) {
// Skip escape char
$cur_pos += $escape_len;
}
$last_value = $cur_pos;
} else if (($cur_char == "\n") || ($cur_char == "\r") || ($cur_char ==
"\r\n")) {
$blank_start_lines = ($cur_pos == 0);
++$cur_pos;
$cur_pos = $cur_pos + strspn($line, "\n\r", $cur_pos);
if (! $blank_start_lines) {
$complete = true;
} else {
$last_value = $cur_pos;
continue;
}
}
if ($cur_char == $delim || $complete) {
if (is_null($fields)) {
$fields = array();
}
$fields[] = $cur_value . trim(mb_substr($line, $last_value, $cur_pos - $last_value));
$last_value = $cur_pos + $cur_len;
$cur_value = '';
} else if ($cur_char == $enclosure) {
if ($in_value) {
$cur_value .= mb_substr($line, $last_value, $cur_pos - $last_value);
}
$last_value = $cur_pos + $cur_len;
$in_value = ! $in_value;
}
if ($complete) {
break;
}
$cur_pos += $cur_len;
}
}
}
fseek($file_handle, $cur_pos - strlen($line), SEEK_CUR);
return $fields;
}
?>