datasn.io
datasn.io

Reputation: 12867

fputcsv() doesn't escape double quotes?

Consider this code:

$escapeChar = '"';

$source = fopen('E:/1.csv', 'r');
$row = fgetcsv($source, null, ',', '"', $escapeChar);
fclose($source);

$writeTo = fopen('E:/2.csv', 'w');
fputcsv($writeTo, $row, ',', '"', $escapeChar);
fclose($writeTo);

$read = fopen('E:/2.csv', 'r');
$row = fgetcsv($read, null, ',', '"', $escapeChar);

print_r($row);

With 1.csv like this:

"Affordable Dentist.""","Mon - Thu: 8:00 am - 5:00 pm Fri: 8:00 am - 1:00 pm Sat - Sun Closed\",,,"amex, cash, check, diners club, discover"

Run the code and it output:

Array
(
    [0] => Affordable Dentist.",Mon - Thu: 8:00 am - 5:00 pm Fri: 8:00 am - 1:00 pm Sat - Sun Closed\"
    [1] =>
    [2] =>
    [3] => amex, cash, check, diners club, discover
)

Then change $escapeChar:

$escapeChar = '\\';

And run the code again which output:

Array
(
    [0] => Affordable Dentist."
    [1] => Mon - Thu: 8:00 am - 5:00 pm Fri: 8:00 am - 1:00 pm Sat - Sun Closed\",,,amex
    [2] =>  cash
    [3] =>  check
    [4] =>  diners club
    [5] =>  discover"
)

It just seems whichever I use for the $escapeChar, '\\' or '"', it's wrong.

The correct final result should be like this:

Array
(
    [0] => Affordable Dentist."
    [1] => Mon - Thu: 8:00 am - 5:00 pm Fri: 8:00 am - 1:00 pm Sat - Sun Closed\
    [2] =>
    [3] =>
    [4] => amex, cash, check, diners club, discover
)

How to make it right here so whatever CSV file read (1.csv) can be output correctly (2.csv) and then the output (2.csv) can again be parsed correctly?

Upvotes: 2

Views: 2558

Answers (3)

Ja͢ck
Ja͢ck

Reputation: 173522

This proprietary escaping mechanism has been around for a long time, but since 7.4 you can switch this off:

The escape_char parameter now also accepts an empty string to disable the proprietary escape mechanism.

This would be your new code:

fputcsv($writeTo, $row, ',', '"', '');
//                                ^^ empty escape character

It will give the following output:

"Affordable Dentist.""","Mon - Thu: 8:00 am - 5:00 pm Fri: 8:00 am - 1:00 pm Sat - Sun Closed\",,,"amex, cash, check, diners club, discover"

References

Upvotes: 2

ArchCodeMonkey
ArchCodeMonkey

Reputation: 2384

To elaborate a bit more on the answer from @murat-tutumlu the problem is because you're using the double quote character as both the escape character and the enclosure character parameters to fgetcsv() and fputcsv(). The steps when reading the first item are:

  1. Read the item = "Affordable Dentist."""
  2. Remove the enclosure character = Affordable Dentist.""
  3. Process the escape character = Affordable Dentist."

When you switch to using the backslash character as the escape character for all operations then the second item escapes the ending enclosure character and breaks the parsing in a different way.

I would recommend using a different escape character in your source data if possible. If you can't change the data then you can change your code to use double quote as the escape character for the first call to fgetcsv() and then switch to an unused character for the subsequent calls.

$escapeChar = '"';

$source = fopen('E:/1.csv', 'r');
$row = fgetcsv($source, null, ',', '"', $escapeChar);
fclose($source);

// Need to use a different escape character from here
$escapeChar = '^';

$writeTo = fopen('E:/2.csv', 'w');
fputcsv($writeTo, $row, ',', '"', $escapeChar);
fclose($writeTo);

$read = fopen('E:/2.csv', 'r');
$row = fgetcsv($read, null, ',', '"', $escapeChar);

print_r($row);

Upvotes: 2

Murat Tutumlu
Murat Tutumlu

Reputation: 780

You need to use escape character for both fgetcsv() and fputcsv():

$objRow = array (
  'general_info' => 'Affordable Dentist."',
  'regular_hours' => 'Mon - Thu: 8:00 am - 5:00 pm Fri: 8:00 am - 1:00 pm Sat - Sun Closed',
  'extra_phones' => '',
  'services_products' => '',
  'payment' => 'amex, cash, check, diners club, discover',
);

$csvHandle = fopen('test.csv', 'w');
fputcsv($csvHandle, $objRow, ',', '"', '\\');
fclose($csvHandle);

$csvHandle = fopen('test.csv', 'r');
$row = fgetcsv($csvHandle, null, ',', '"', '\\');
print_r($row);

Upvotes: 0

Related Questions