note 120104 added to function.fgetcsv
| From: | DanielKlein | Date: | Tue, 01 Nov 2016 01:26:43 +0000 |
| Subject: | note 120104 added to function.fgetcsv | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-206997@lists.php.net to get a copy of this message | ||
The $escape parameter is completely unintuitive, but it is not broken. Here is a breakdown of
fgetcsv()'s behaviour. In the examples I've used underscores (_) to show spaces and
brackets ([]) to show individual fields:
- Leading whitespace in each field will be stripped if it comes immediately before an enclosure:
___"foo" -> [foo]
- There can only be one enclosure per field, although it will be concatenated with any data that
appears between the end enclosure and the next delimiter/new line, including any trailing
whitespaces ___"foo"_"bar"__ -> [foo_"bar"__]
- If the field does not start with (leading whitespace +) an enclosure, the whole field is
interpreted as raw data, even if enclosure characters appear elsewhere within the field:
_foo"bar"_ -> [_foo"bar"_]
- Delimiters cannot be escaped outside enclosures, they have to be enclosed instead. Delimiters
don't need to be escaped inside enclosures: "foo,bar","baz,qux" ->
[foo,bar][baz,qux]; foo\,bar -> [foo\][bar]; "foo\,bar" -> [foo\,bar]
- Double enclosures inside single enclosures are converted to single enclosures: "foobar"
-> [foobar]; "foo""bar" -> [foo"bar];
"""foo""" -> ["foo"]; ""foo"" ->
[foo""] (empty enclosure followed by raw data)
- The $escape parameter works as expected, but unlike enclosures DOES NOT get unescaped. It is
necessary to unescape the data elsewhere in the code: "\"foo\"" ->
[\"foo\"]; "foo\"bar" -> [foo\"bar]
Note: the following data (which is a very common problem) is invalid: "\". Its structure
is equivalent to "@ or in other words, an open enclosure, some data and no closing enclosure.
The following functions can be used to get the expected behaviour:
<?php
// Removes escape characters before both enclosures and escapes, but leaves everything else
untouched, similiar to single quoting
function fgetcsv_unescape_enclosures_and_escapes($fh, $length = 0, $delimiter = ',',
$enclosure = '"', $escape = '\\') {
$fields = fgetcsv($fh, $length, $delimiter, $enclosure, $escape);
if ($fields) {
$regex_enclosure = preg_quote($enclosure);
$regex_escape = preg_quote($escape);
$fields = preg_replace("/{$regex_escape}({$regex_enclosure}|{$regex_escape})/",
'$1', $fields);
}
return $fields;
}
// Does NOT remove a lone escape character at the end of a field
function fgetcsv_unescape_all($fh, $length = 0, $delimiter = ',', $enclosure =
'"', $escape = '\\') {
$fields = fgetcsv($fh, $length, $delimiter, $enclosure, $escape);
if ($fields) {
$regex_escape = preg_quote($escape);
$fields = preg_replace("/{$regex_escape}(.)/s", '$1', $fields);
}
return $fields;
}
// Removes lone escape characters at the end of fields
function fgetcsv_unescape_all_strip_last($fh, $length = 0, $delimiter = ',', $enclosure =
'"', $escape = '\\') {
$fields = fgetcsv($fh, $length, $delimiter, $enclosure, $escape);
if ($fields) {
$regex_escape = preg_quote($escape);
$fields = preg_replace("/{$regex_escape}(.?)/s", '$1', $fields);
}
return $fields;
}
?>
Caution: ideally, there shouldn't be any unescaped escape characters outside enclosures; the
field should be enclosed and escaped instead. If there are any, they could end up being removed as
well, depending on the function used.
----
Server IP: 72.52.91.14
Probable Submitter: 49.177.154.6
----
Manual Page -- http://php.net/manual/en/function.fgetcsv.php
Edit -- https://master.php.net/note/edit/120104
Del: integrated -- https://master.php.net/note/delete/120104/integrated
Del: useless -- https://master.php.net/note/delete/120104/useless
Del: bad code -- https://master.php.net/note/delete/120104/bad+code
Del: spam -- https://master.php.net/note/delete/120104/spam
Del: non-english -- https://master.php.net/note/delete/120104/non-english
Del: in docs -- https://master.php.net/note/delete/120104/in+docs
Del: other reasons-- https://master.php.net/note/delete/120104
Reject -- https://master.php.net/note/reject/120104
Search -- https://master.php.net/manage/user-notes.php