Search code examples
phpcsvutf-8export-to-csvbyte-order-mark

Unable to write on the first line of csv using php


Background

I am using php to write a csv file contain Chinese character. However,they cannot display well. I found the problem is excel does not read utf8 without BOM. And I need to add the BOM on the first line and it works if I put \xEF\xBB\xBF on the first line using Notepad++.

However, the application of output csv is for users. I cannot told the user to do this by themselves, so I must do this by PHP.


Problem

Here is the code I use to write the bom tag.

<?php
 header('Content-Description: File Transfer');
 header('Content-Type: application/octet-stream'); 
 header('Content-Disposition: attachment; filename=file.csv');
 header('Content-Transfer-Encoding: binary');
 header('Expires: 0');
 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
 header('Pragma: public');
 $output = fopen('php://output', 'w');
 $BOM = "\xEF\xBB\xBF";
 $fwrite($output,$BOM)
?>

This is the result I expected
+-----------------+
|\xEF\xBB\xBF|
|-----empty line|
|----my content|
|----my content|
+-----------------+
However, the result is
+-----------------+
|-----empty line|
|\xEF\xBB\xBF|
|----my content|
|----my content|
+-----------------+
I tried fwrite, fputs, fputcsv still cannot put the BOM tag on the first line
Is there any way to put it on the first line
Or is there any other way to write a excel readable csv file that can open directly?


p.s. my chinese data is from MySQL and used:
mysql_query("set names utf8"); mysql_query("set character_set_client='utf8'"); mysql_query("set character_set_results='utf8'"); mysql_query ("set collation_connection='utf8_general_ci'");


tl;dr When I write the csv, it start to write on the second line. How to write a file start on the first line of the file?


Solution

  • From my experience I tell you that the first empty line is because of some forgotten space/empty line outside php tags.

    To obtain the desired empty line after \xEF line try this:

    $output = fopen('php://output', 'w');
     $BOM = "\xEF\xBB\xBF
    ";
     $fwrite($output,$BOM)
    

    Also, if there are included files in your php script also check them for empty spaces/lines outside the php tags.