Search code examples
phpcsvline-endings

How can I change the line endings used by fputcsv?


I create a CSV file for download by our client using

$output = fopen('php://output', 'w');

and using fputcsv() to write data to a CSV file which is downloaded by the client.

I am running PHP on Linux and consequently the line endings are not interpreted by many Windows applications.

I could write the CSV file to a directory on the server, read it back in and perform a str_replace() from \n to \r\n, but this seems a rather clunky way of solving the problem. Is there a way to perform the conversion without creating a physical file?


Solution

  • You could use stream filters to accomplish this. This example writes to a physical file, but it should work fine for php://output as well.

    // filter class that applies CRLF line endings
    class crlf_filter extends php_user_filter
    {
        function filter($in, $out, &$consumed, $closing)
        {
            while ($bucket = stream_bucket_make_writeable($in)) {
                // make sure the line endings aren't already CRLF
                $bucket->data = preg_replace("/(?<!\r)\n/", "\r\n", $bucket->data);
                $consumed += $bucket->datalen;
                stream_bucket_append($out, $bucket);
            }
            return PSFS_PASS_ON;
        }
    }
    // register the filter
    stream_filter_register('crlf', 'crlf_filter');
    
    $f = fopen('test.csv', 'wt');
    // attach filter to output file
    stream_filter_append($f, 'crlf');
    // start writing
    fputcsv($f, array('1 1', '2 2'));
    fclose($f);