Как создать файл csv php

Обновлено: 06.07.2024

Данная функция выполняет разбор строки в формате CSV и возвращает массив с полученными из строки полями.

Замечание:

Эта функция принимает во внимание настройки локали. К примеру, если LC_CTYPE установлена в en_US.UTF-8 , то строки в однобайтовой кодировке будут неправильно прочитаны этой функцией.

Список параметров

Устанавливает разделитель поля (только один однобайтовый символ).

Устанавливает символ ограничителя поля (только один однобайтовый символ).

Устанавливает экранирующий символ (не более одного однобайтового символа). По умолчанию равен обратному слешу ( \ ). Пустая строка ( "" ) отключает проприетарный механизм экранирования.

Замечание: Обычно символ enclosure экранируется внутри поля путём его удваивания; однако, символ escape в качестве альтернативы. Поэтому значения по умолчанию этих параметров "" и \" имеют одинаковое значение. Помимо разрешения экранировать символ enclosure символ escape не имеет особого смысла; он даже не предназначен для самого экранирования.

Возвращаемые значения

Возвращает индексированный массив, содержащий полученные из строки поля.

Список изменений

Версия Описание
7.4.0 Теперь пустой параметр escape будет интерпретироваться как требование отключения проприетарного механизма экранирования. Ранее пустая строка обозначала использование символа экранирования по умолчанию.

Смотрите также

  • fgetcsv() - Читает строку из файла и производит разбор данных CSV

User Contributed Notes 35 notes

[Editor's Note (cmb): that does not produce the desired results, if fields contain linebreaks.]

Handy one liner to parse a CSV file into an array

$csv = array_map ( 'str_getcsv' , file ( 'data.csv' ));

Based on James' line, this will create an array of associative arrays with the first row column headers as the keys.

This will yield something like
[2] => Array
(
[Campaign ID] => 295095038
[Ad group ID] => 22460178158
Как создать файл csv php => 3993587178

As the str_getcsv(), unlike to fgetcsv(), does not parse the rows in CSV string, I have found following easy workaround:

<?php
$Data = str_getcsv ( $CsvString , "\n" ); //parse the rows
foreach( $Data as & $Row ) $Row = str_getcsv ( $Row , ";" ); //parse the items in rows
?>

Why not use explode() instead of str_getcsv() to parse rows? Because explode() would not treat possible enclosured parts of string or escaped characters correctly.

Here is a quick and easy way to convert a CSV file to an associated array:

$header = NULL ;
$data = array();
if (( $handle = fopen ( $filename , 'r' )) !== FALSE )
while (( $row = fgetcsv ( $handle , 1000 , $delimiter )) !== FALSE )
if(! $header )
$header = $row ;
else
$data [] = array_combine ( $header , $row );
>
fclose ( $handle );
>
return $data ;
>

I wanted the best of the 2 solutions by james at moss dot io and Jay Williams (csv_to_array()) - create associative array from a CSV file with a header row.

$array = array_map ( 'str_getcsv' , file ( 'data.csv' ));

$header = array_shift ( $array );

array_walk ( $array , '_combine_array' , $header );

function _combine_array (& $row , $key , $header ) $row = array_combine ( $header , $row );
>

array_walk() and array_map() - 39 opcodes
csv_to_array() - 69 opcodes

PHP is failing when parsing UTF-8 with Byte Order Mark. Strip it with this one from string before passing it to csv parser:

<?php
$bom = pack ( 'CCC' , 0xEF , 0xBB , 0xBF );
if ( strncmp ( $yourString , $bom , 3 ) === 0 ) $body = substr ( $yourString , 3 );
>
?>

Like some other users here noted, str_getcsv() cannot be used if you want to comply with either the RFC or with most spreadsheet tools like Excel or Google Docs.

These tools do not escape commas or new lines, but instead place double-quotes (") around the field. If there are any double-quotes in the field, these are escaped with another double-quote (" becomes ""). All this may look odd, but it is what the RFC and most tools do .

For instance, try exporting as .csv a Google Docs spreadsheet (File > Download as > .csv) which has new lines and commas as part of the field values and see how the .csv content looks, then try to parse it using str_getcsv() . it will spectacularly regardless of the arguments you pass to it.

- doesn't use any for or while loops,
- it allows for any separator (any string of any length),
- option to skip empty lines,
- option to trim fields,
- can handle UTF8 data too (although .csv files are likely non-unicode).

Here is the more human readable version of the function:

// returns a two-dimensional array or rows and fields

function parse_csv ( $csv_string , $delimiter = "," , $skip_empty_lines = true , $trim_fields = true )
$enc = preg_replace ( '/(?<!")""/' , '!!Q!!' , $csv_string );
$enc = preg_replace_callback (
'/"(.*?)"/s' ,
function ( $field ) return urlencode ( utf8_encode ( $field [ 1 ]));
>,
$enc
);
$lines = preg_split ( $skip_empty_lines ? ( $trim_fields ? '/( *\R)+/s' : '/\R+/s' ) : '/\R/s' , $enc );
return array_map (
function ( $line ) use ( $delimiter , $trim_fields ) $fields = $trim_fields ? array_map ( 'trim' , explode ( $delimiter , $line )) : explode ( $delimiter , $line );
return array_map (
function ( $field ) return str_replace ( '!!Q!!' , '"' , utf8_decode ( urldecode ( $field )));
>,
$fields
);
>,
$lines
);
>

?>

Since this is not using any loops, you can actually write it as a one-line statement (one-liner).

Here's the function using just one line of code for the function body, formatted nicely though:

// returns the same two-dimensional array as above, but with a one-liner code

function parse_csv ( $csv_string , $delimiter = "," , $skip_empty_lines = true , $trim_fields = true )
return array_map (
function ( $line ) use ( $delimiter , $trim_fields ) return array_map (
function ( $field ) return str_replace ( '!!Q!!' , '"' , utf8_decode ( urldecode ( $field )));
>,
$trim_fields ? array_map ( 'trim' , explode ( $delimiter , $line )) : explode ( $delimiter , $line )
);
>,
preg_split (
$skip_empty_lines ? ( $trim_fields ? '/( *\R)+/s' : '/\R+/s' ) : '/\R/s' ,
preg_replace_callback (
'/"(.*?)"/s' ,
function ( $field ) return urlencode ( utf8_encode ( $field [ 1 ]));
>,
$enc = preg_replace ( '/(?<!")""/' , '!!Q!!' , $csv_string )
)
)
);
>

?>

Replace !!Q!! with another placeholder if you wish.

@normadize - that is a nice start, but it fails on situations where a field is empty but quoted (returning a string with one double quote instead of an empty string) and cases like """""foo""""" that should result in ""foo"" but instead return "foo". I also get a row with 1 empty field at the end because of the final CRLF in the CSV. Plus, I don't really like the !!Q!! magic or urlencoding to get around things. Also, \R doesn't work in pcre on any of my php installations.

Here is my take on this, without anonymous functions (so it works on PHP < 5.3), and without your options (because I believe the only correct way to parse according to the RFC would be $skip_empty_lines = false and $trim_fields = false).

//parse a CSV file into a two-dimensional array
//this seems as simple as splitting a string by lines and commas, but this only works if tricks are performed
//to ensure that you do NOT split on lines and commas that are inside of double quotes.
function parse_csv($str)
//match all the non-quoted text and one series of quoted text (or the end of the string)
//each group of matches will be parsed with the callback, with $matches[1] containing all the non-quoted text,
//and $matches[3] containing everything inside the quotes
$str = preg_replace_callback('/([^"]*)("((""|[^"])*)"|$)/s', 'parse_csv_quotes', $str);

//remove the very last newline to prevent a 0-field array for the last line
$str = preg_replace('/\n$/', '', $str);

//split on LF and parse each line with a callback
return array_map('parse_csv_line', explode("\n", $str));
>

//replace all the csv-special characters inside double quotes with markers using an escape sequence
function parse_csv_quotes($matches)
//anything inside the quotes that might be used to split the string into lines and fields later,
//needs to be quoted. The only character we can guarantee as safe to use, because it will never appear in the unquoted text, is a CR
//So we're going to use CR as a marker to make escape sequences for CR, LF, Quotes, and Commas.
$str = str_replace("\r", "\rR", $matches[3]);
$str = str_replace("\n", "\rN", $str);
$str = str_replace('""', "\rQ", $str);
$str = str_replace(',', "\rC", $str);

//The unquoted text is where commas and newlines are allowed, and where the splits will happen
//We're going to remove all CRs from the unquoted text, by normalizing all line endings to just LF
//This ensures us that the only place CR is used, is as the escape sequences for quoted text
return preg_replace('/\r\n?/', "\n", $matches[1]) . $str;
>

//split on comma and parse each field with a callback
function parse_csv_line($line)
return array_map('parse_csv_field', explode(',', $line));
>

//restore any csv-special characters that are part of the data
function parse_csv_field($field) $field = str_replace("\rC", ',', $field);
$field = str_replace("\rQ", '"', $field);
$field = str_replace("\rN", "\n", $field);
$field = str_replace("\rR", "\r", $field);
return $field;
>

I found myself wanting to parse a CSV and didn't have access to str_getcsv, so I wrote substitute for PHP < 5.3, hope it helps someone out there stuck in the same situation.

<?php
if (! function_exists ( 'str_getcsv' )) <
function str_getcsv ( $input , $delimiter = ',' , $enclosure = '"' , $escape = '\\' , $eol = '\n' ) <
if ( is_string ( $input ) && !empty( $input )) <
$output = array();
$tmp = preg_split ( "/" . $eol . "/" , $input );
if ( is_array ( $tmp ) && !empty( $tmp )) <
while (list( $line_num , $line ) = each ( $tmp )) <
if ( preg_match ( "/" . $escape . $enclosure . "/" , $line )) <
while ( $strlen = strlen ( $line )) <
$pos_delimiter = strpos ( $line , $delimiter );
$pos_enclosure_start = strpos ( $line , $enclosure );
if (
is_int ( $pos_delimiter ) && is_int ( $pos_enclosure_start )
&& ( $pos_enclosure_start < $pos_delimiter )
) <
$enclosed_str = substr ( $line , 1 );
$pos_enclosure_end = strpos ( $enclosed_str , $enclosure );
$enclosed_str = substr ( $enclosed_str , 0 , $pos_enclosure_end );
$output [ $line_num ][] = $enclosed_str ;
$offset = $pos_enclosure_end + 3 ;
> else <
if (empty( $pos_delimiter ) && empty( $pos_enclosure_start )) <
$output [ $line_num ][] = substr ( $line , 0 );
$offset = strlen ( $line );
> else <
$output [ $line_num ][] = substr ( $line , 0 , $pos_delimiter );
$offset = (
!empty( $pos_enclosure_start )
&& ( $pos_enclosure_start < $pos_delimiter )
)
? $pos_enclosure_start
: $pos_delimiter + 1 ;
>
>
$line = substr ( $line , $offset );
>
> else <
$line = preg_split ( "/" . $delimiter . "/" , $line );

/*
* Validating against pesky extra line breaks creating false rows.
*/
if ( is_array ( $line ) && !empty( $line [ 0 ])) <
$output [ $line_num ] = $line ;
>
>
>
return $output ;
> else <
return false ;
>
> else <
return false ;
>
>
>
?>

<?php
Note : The function trims all values unlike str_getcsv ( v5.3 ).
/**
* @link https://github.com/insteps/phputils (for updated code)
* Parse a CSV string into an array for php 4+.
* @param string $input String
* @param string $delimiter String
* @param string $enclosure String
* @return array
*/
function str_getcsv4 ( $input , $delimiter = ',' , $enclosure = '"' )

if( ! preg_match ( "/[ $enclosure ]/" , $input ) ) return (array) preg_replace (array( "/^\\s*/" , "/\\s*$/" ), '' , explode ( $delimiter , $input ));
>

$a = explode ( $token , $t1 );
foreach( $a as $k => $v ) if ( preg_match ( "/^ < $delimiter >/" , $v ) || preg_match ( "/ < $delimiter >$/" , $v ) ) $a [ $k ] = trim ( $v , $delimiter ); $a [ $k ] = preg_replace ( "/ $delimiter /" , " $token " , $a [ $k ]); >
>
$a = explode ( $token , implode ( $token , $a ));
return (array) preg_replace (array( "/^\\s/" , "/\\s$/" , "/ $token2 /" ), array( '' , '' , $enclosure ), $a );

if ( ! function_exists ( 'str_getcsv' )) function str_getcsv ( $input , $delimiter = ',' , $enclosure = '"' ) return str_getcsv4 ( $input , $delimiter , $enclosure );
>
>
?>

After using several methods in the past to create CSV strings without using files (disk IO sucks), I finally decided it's time to write a function to handle it all. This function could use some cleanup, and the variable type test might be overkill for what is needed, I haven't thought about it too much.

Also, I took the liberty of replacing fields with certain data types with strings which I find much easier to work with. Some of you may not agree with those. Also, please note that the type "double" or float has been coded specifically for two digit precision because if I am using a float, it's most likely for currency.

I am sure some of you out there would appreciate this function.

CSV очень удобный формат с точки зрения генерации, поскольку он очень просто устроен. В этой заметке разберемся как устроены файлы с расширением .csv , как их создавать и разбирать (парсить) в PHP. Делается это очень просто.

Ищем WP-разработчика! Фулл-тайм, удаленка, хорошая зарплата, соц. пакет. Подробности.
Компания Boosta.

Ниже приведены простые PHP функции для создания и парсинга csv файлов. Никаких библиотек - для CSV это лишнее!

Формат CSV

Чтобы понимать суть вещей, нужно разобраться в спецификации CSV файлов, как устроен формат. Давайте коротко.

CSV (Comma-Separated Values — значения, разделённые запятыми) — текстовый формат, предназначенный для представления табличных данных.

Каждая строка файла — это одна строка таблицы.

Разделителем значений колонок является символ: , (запятая). Для русского языка используется ; (точка с запятой), потому что в русском запятая используется в дробных числах.

Значения, содержащие зарезервированные символы: " , ; \r\n или \n или \r (двойная кавычка, запятая, точка с запятой, новая строка) обрамляются двойными кавычками " .

Если в значении встречаются двойные кавычки " , то они должны выглядеть как двое кавычек подряд "" .

Это все что нужно знать, чтобы работать с CSV!

Пример для рус. языка:


Пример для англ. языка:


Wiki-справка

Большинство программ под CSV понимают более общий формат DSV (delimiter-separated values — значения разделённые разделителем), допускающий использование иных символов в качестве разделителя. В частности, в русской и других локалях запятая по умолчанию зарезервирована под десятичный разделитель. Поэтому как разделитель используется точка с запятой или табуляция (формат TSV).

Сегодня под CSV понимают набор значений, разделенных какими угодно разделителями, в какой угодно кодировке с какими угодно окончаниями строк. Это значительно затрудняет перенос данных из одних программ в другие, несмотря на всю простоту формата.

Создание CSV файла в PHP

Для создания CSV файла, достаточно создать текстовый файл, используя в нужных местах необходимые разделители столбцов и строк.

Важным моментом, является кодировка файла. Для корректного отображения кириллицы следует использовать кодировку cp1251 (windows-1251).

Разделитель колонок

Для русского языка символом-разделителем является ; (точка с запятой). Для англ. , (запятая).

Строки содержащие спец символы: " , ; \r\n или \n или \r должны быть в двойных кавычках "строка" .

Двойные кавычки внутри строки, нужно «очистить» поставив перед кавычкой еще одну такую же кавычку: строка "csv" превратиться в "строка ""csv""" . Обрамление в кавычки нужно, чтобы можно было внутри значений колонок использовать разделители ; , , и не переживать что что-то сломается при чтении файла.

Разделитель строк

Для разделения строк в csv файлах можно использовать \r\n (возврат каретки и перенос строки, CR LF). В этом случае, если нужен перенос строки внутри значения колонки, то там используется просто \n .

Также, для разделения строки, может использоваться просто \n (перенос строки, LF). В этом случае, перенос строки внутри значения колонки должен обозначаться как \r (возврат каретки CR).

Функция для создания CSV файла


меню

Чтение CSV файла в PHP

Когда нужно получить данные из CSV файла, т.е. разобрать его и получить данные в переменную, можно использовать встороенную в PHP функцию str_getcsv() .

Есть еще функция fgetcsv() , но она оказалась капризной и не всегда работает как нужно (может перепутать переносы строк).

Вариант на базе функции str_getcsv() :

Конвертация .lsx , .xlsx файла в .csv

Чтобы перевести Excel файл в CSV, нужно открыть его в Excel и сохранить в формате .csv :


Если такую конвертацию нужно сделать программно, смотрите в сторону онлайн конвертеров с API или готовых библиотек.

Сталкивались с такой задачей и знаете более универсальный способ? Прошу поделиться в комментариях.

Я столкнулся и потратил несколько часов перебирая всякий не универсальный «мусор» из гугла - то одно не работает, то другое, то библиотеку нужно ставить «хитро-мудрую». Так и появилась эта заметка.

Тема, конечно, интересная. Только этот код в реальных условиях работать не будет.

Что с ним не так?

1) Разделитель поля может быть любой. Например, '\', '|' или ещё что похуже.
2) Символ ограничителя поля может быть как двойная, так и одинарная ковычка.
3) Неплохо бы использовать unset в коде. Память на сервере всё-таки не резиновая. Одно дело загрузка файла с пару сотен строк кода, а другое если их пару десятков миллионов.

1) Ты параметр $col_delimiter не увидел похоже, суй туда какой угодно разделитель!

2) Для текущего кода (обоих) это учитывается: в первом создается строка с двойной кавычкой и только. Во втором строка парсится PHP функцией str_getcsv() которая обе кавычки понимает.

3) В каком месте там unset по твоему поможет хорошо избавится от потерь памяти? Если у тебя файл выходит за пределы памяти, что редкость с текущими параметрами серверов, то это пожалуй экстра случай и подход уже нужен будет принципиально другой. Файл читать или записывать нужно будет частями или построчно, а не так целиком. По аналогии ты в ВП запихай 50 000 рубрик и все приехали, нужно будет костыли вставлять для нормальной работы. Но ВП почему-то самая популярная CMS, как же так? Я не писал код на все случаи жизни, код покрывает 80% случаев, остальное уже требует отдельного подхода, а этот код можно взять за основу.

Этот код в реальных условиях у меня работает! Может там и есть баги, но я их не встречал.

П.С. просмотрел второй код, добавил unset() маловероятно что много толку от этого, но лишним не будет.

Не "суй туда какой угодно разделитель", а все возможные разделители для csv файлов. Ты бы ещё менеджеру предложил указывать разделитель для файла, который он загружает

"с текущими параметрами серверов". Поверь, кривым кодом можно положить сервер даже с очень хорошими характеристиками. Я обычно беру за правило, если переменная больше не будет использоваться она должна умереть (или обнулиться). Когда поработаешь с хайлоудом, то начинаешь понимать цену памяти)

И вообще, если пишешь рабочую программу, нужно это делать хорошо, а не в стиле "мой первый скрипт"!

fputcsv() форматирует строку (переданную в виде массива fields ) в виде CSV и записывает её (заканчивая переводом строки) в указанный файл stream .

Список параметров

Указатель на файл должен быть корректным и указывать на файл, успешно открытый функциями fopen() или fsockopen() (и всё ещё не закрытый функцией fclose() ).

Массив строк ( string ).

Дополнительный параметр separator устанавливает разделитель полей (только один однобайтовый символ).

Дополнительный параметр enclosure устанавливает ограничитель полей (только один однобайтовый символ).

Необязательный параметр escape задаёт экранирующий символ (не более одного однобайтового символа). Пустая строка ( "" ) отключает проприетарный механизм экранирования.

Необязательный параметр eol задаёт настраиваемую последовательность конца строки.

Замечание:

Если символ enclosure содержится в поле, он будет экранирован путём его удвоения, если ему не предшествует escape .

Возвращаемые значения

Возвращает длину записанной строки или false в случае возникновения ошибки.

Список изменений

Версия Описание
8.1.0 Добавлен необязательный параметр eol .
7.4.0 Теперь параметр escape может принимать пустую строку для отключения проприетарного механизма экранирования.

Примеры

$list = array (
array( 'aaa' , 'bbb' , 'ccc' , 'dddd' ),
array( '123' , '456' , '789' ),
array( '"aaa"' , '"bbb"' )
);

$fp = fopen ( 'file.csv' , 'w' );

foreach ( $list as $fields ) fputcsv ( $fp , $fields );
>

Вышеуказанный пример запишет в файл file.csv следующее:

Примечания

Замечание: Если у вас возникают проблемы с распознаванием PHP концов строк при чтении или создании файлов на Macintosh-совместимом компьютере, включение опции auto_detect_line_endings может помочь решить проблему.

Смотрите также

  • fgetcsv() - Читает строку из файла и производит разбор данных CSV

User Contributed Notes 27 notes

If you need to send a CSV file directly to the browser, without writing in an external file, you can open the output and use fputcsv on it..

<?php
$out = fopen ( 'php://output' , 'w' );
fputcsv ( $out , array( 'this' , 'is some' , 'csv "stuff", you know.' ));
fclose ( $out );
?>

Sometimes it's useful to get CSV line as string. I.e. to store it somewhere, not in on a filesystem.

<?php
function csvstr (array $fields ) : string
$f = fopen ( 'php://memory' , 'r+' );
if ( fputcsv ( $f , $fields ) === false ) return false ;
>
rewind ( $f );
$csv_line = stream_get_contents ( $f );
return rtrim ( $csv_line );
>
?>

If you need to save the output to a variable (e.g. for use within a framework) you can write to a temporary memory-wrapper and retrieve it's contents:

<?php
// output up to 5MB is kept in memory, if it becomes bigger it will automatically be written to a temporary file
$csv = fopen ( 'php://temp/maxmemory:' . ( 5 * 1024 * 1024 ), 'r+' );

fputcsv ( $csv , array( 'blah' , 'blah' ));

// put it all in a variable
$output = stream_get_contents ( $csv );
?>

if you want make UTF-8 file for excel, use this:

$fp = fopen($filename, 'w');
//add BOM to fix UTF-8 in Excel
fputs($fp, $bom =( chr(0xEF) . chr(0xBB) . chr(0xBF) ));

Please note, that fputcsv ist not always enclosing strings with the enclosure character.

<?php
$fh = fopen ( 'file.csv' , 'w' );

$a = [ 'One 1' , 'Two' , 'Three 3' ];

fputcsv ( $fh , $a , "\t" );

fclose ( $fh );
?>

results in a file containing the line:
"One 1" Two "Three 3"

It seems that only strings containing at least one of the following characters are enclosed:

- the delimiter character
- the enclosure character
- the escape character
- \n (new line)
- \r (line feed)
- \t (tab)
- blank

I hope this saves you the hour it took me to get to the bottom of this behaviour.

Using fputcsv to output a CSV with a tab delimiter is a little tricky since the delimiter field only takes one character.
The answer is to use the chr() function. The ascii code for tab is 9, so chr(9) returns a tab character.

<?php
fputcsv ( $fp , $foo , '\t' ); //won't work
fputcsv ( $fp , $foo , ' ' ); //won't work

it should be:
<?php
fputcsv ( $fp , $foo , "\t" );
?>
you just forgot that single quotes are literal. meaning whatever you put there that's what will come out so '\t' would be same as 't' because \ in that case would be only used for escaping but if you use double quotes then that would work.

Utility function to output a mysql query to csv with the option to write to file or send back to the browser as a csv attachment.

<?php
function query_to_csv ( $db_conn , $query , $filename , $attachment = false , $headers = true )

if( $attachment ) // send response headers to the browser
header ( 'Content-Type: text/csv' );
header ( 'Content-Disposition: attachment;filename=' . $filename );
$fp = fopen ( 'php://output' , 'w' );
> else $fp = fopen ( $filename , 'w' );
>

$result = mysql_query ( $query , $db_conn ) or die( mysql_error ( $db_conn ) );

if( $headers ) // output header row (if at least one row exists)
$row = mysql_fetch_assoc ( $result );
if( $row ) fputcsv ( $fp , array_keys ( $row ));
// reset pointer back to beginning
mysql_data_seek ( $result , 0 );
>
>

while( $row = mysql_fetch_assoc ( $result )) fputcsv ( $fp , $row );
>

// Using the function
$sql = "SELECT * FROM table" ;
// $db_conn should be a valid db handle

// output as an attachment
query_to_csv ( $db_conn , $sql , "test.csv" , true );

// output to file system
query_to_csv ( $db_conn , $sql , "test.csv" , false );
?>

Alright, after playing a while, I'm confident the following replacement function works in all cases, including the ones for which the native fputcsv function fails. If fputcsv fails to work for you (particularly with mysql csv imports), try this function as a drop-in replacement instead.

Arguments to pass in are exactly the same as for fputcsv, though I have added an additional $mysql_null boolean which allows one to turn php null's into mysql-insertable nulls (by default, this add-on is disabled, thus working identically to fputcsv [except this one works!]).

function fputcsv2 ( $fh , array $fields , $delimiter = ',' , $enclosure = '"' , $mysql_null = false ) <
$delimiter_esc = preg_quote ( $delimiter , '/' );
$enclosure_esc = preg_quote ( $enclosure , '/' );

$output = array();
foreach ( $fields as $field ) <
if ( $field === null && $mysql_null ) <
$output [] = 'NULL' ;
continue;
>

$output [] = preg_match ( "/(?: $ < delimiter_esc >| $ < enclosure_esc >|\s)/" , $field ) ? (
$enclosure . str_replace ( $enclosure , $enclosure . $enclosure , $field ) . $enclosure
) : $field ;
>

fwrite ( $fh , join ( $delimiter , $output ) . "\n" );
>

// the _EXACT_ LOAD DATA INFILE command to use
// (if you pass in something different for $delimiter
// and/or $enclosure above, change them here too;
// but _LEAVE ESCAPED BY EMPTY!_).
/*
LOAD DATA INFILE
'/path/to/file.csv'

INTO TABLE
my_table

FIELDS TERMINATED BY
','

OPTIONALLY ENCLOSED BY
'"'

LINES TERMINATED BY
'\n'
*/

the solution for how to solve the encoding problem while converting an array to csv file is below.

$fp = fopen('php://memory', 'w');
//add BOM to fix UTF-8 in Excel
fputs($fp, $bom =( chr(0xEF) . chr(0xBB) . chr(0xBF) ));
// output the column headings
//fputcsv($fp, array('Topic', 'Title', 'URL', 'Keywords', 'Score', 'FB_count', 'TW_count', '|'));
if(isset($trend)) foreach ( $trend as $myField ) fputcsv($fp, $myField, '|');
>
>

If you do not want to enclose strings (because you're managing that yourself or your content is already enclosed?), note that you cannot pass an empty enclosure to fputcsv. The function requires one character for that parameter. chr(0) works well:

fputcsv($handle, $fields, ",", chr(0));

This function accommodates for that as well, by forcibly enclosing that first value in quotes (when this doesn't occur automatically). It would be fairly simple to modify this function to use another delimiter if need be and I leave that as an exercise to the reader. So quite simply, this function is used for outputting CSV data to a CSV file in a way that is safe for use with Windows applications. It takes two parameters + one optional parameter: the location of where the file should be saved, an array of data rows, and an optional array of column headings. (Technically you could omit the headings array and just include it as the first row of the data, but it is often useful to keep this data stored in different arrays in practice.)

function mssafe_csv ( $filepath , $data , $header = array())
<
if ( $fp = fopen ( $filepath , 'w' ) ) <
$show_header = true ;
if ( empty( $header ) ) <
$show_header = false ;
reset ( $data );
$line = current ( $data );
if ( !empty( $line ) ) <
reset ( $line );
$first = current ( $line );
if ( substr ( $first , 0 , 2 ) == 'ID' && ! preg_match ( '/["\\s,]/' , $first ) ) <
array_shift ( $data );
array_shift ( $line );
if ( empty( $line ) ) <
fwrite ( $fp , "\" < $first >\"\r\n" );
> else <
fwrite ( $fp , "\" < $first >\"," );
fputcsv ( $fp , $line );
fseek ( $fp , - 1 , SEEK_CUR );
fwrite ( $fp , "\r\n" );
>
>
>
> else <
reset ( $header );
$first = current ( $header );
if ( substr ( $first , 0 , 2 ) == 'ID' && ! preg_match ( '/["\\s,]/' , $first ) ) <
array_shift ( $header );
if ( empty( $header ) ) <
$show_header = false ;
fwrite ( $fp , "\" < $first >\"\r\n" );
> else <
fwrite ( $fp , "\" < $first >\"," );
>
>
>
if ( $show_header ) <
fputcsv ( $fp , $header );
fseek ( $fp , - 1 , SEEK_CUR );
fwrite ( $fp , "\r\n" );
>
foreach ( $data as $line ) <
fputcsv ( $fp , $line );
fseek ( $fp , - 1 , SEEK_CUR );
fwrite ( $fp , "\r\n" );
>
fclose ( $fp );
> else <
return false ;
>
return true ;
>

I converted this from the PHP source code. This replicates PHP5 functionality exactly, whereas the other examples here do not.

if (! function_exists ( 'fputcsv' ))

function fputcsv (& $handle , $fields = array(), $delimiter = ',' , $enclosure = '"' ) $str = '' ;
$escape_char = '\\' ;
foreach ( $fields as $value ) if ( strpos ( $value , $delimiter ) !== false ||
strpos ( $value , $enclosure ) !== false ||
strpos ( $value , "\n" ) !== false ||
strpos ( $value , "\r" ) !== false ||
strpos ( $value , "\t" ) !== false ||
strpos ( $value , ' ' ) !== false ) $str2 = $enclosure ;
$escaped = 0 ;
$len = strlen ( $value );
for ( $i = 0 ; $i < $len ; $i ++) if ( $value [ $i ] == $escape_char ) $escaped = 1 ;
> else if (! $escaped && $value [ $i ] == $enclosure ) $str2 .= $enclosure ;
> else $escaped = 0 ;
>
$str2 .= $value [ $i ];
>
$str2 .= $enclosure ;
$str .= $str2 . $delimiter ;
> else $str .= $value . $delimiter ;
>
>
$str = substr ( $str , 0 ,- 1 );
$str .= "\n" ;
return fwrite ( $handle , $str );
>

[EDIT BY danbrown AT php DOT net: This is a revised function with a few bugfixes and improvements done by this author. The original function example was written by arthur AT mclean DOT ws, and rewritten between by arthur AT korn DOT ch.]

- when calling str_replace(), you must assign $cell the return value or nothing gets saved

- when using strchr(), you should explicitly check !== FALSE, or it'll treat a return value of 0 (found the character at string position 0) as FALSE

- Excel seems to quote not only fields containing commas, but fields containing quotes as well, so I've added another strchr() for quotes; I'm not saying Microsoft knows the correct way for sure, but it seems reasonable to me

- the original function put a space after each comma; that might be legal, I don't know, but I've never seen it (and I don't think it is, because then how would you indicate you wanted a field to start with a space other than by quoting it?)

- the original function didn't correctly return the length of the data outputted

Here's the function, fixed up a bit:

<?php
function fputcsv ( $handle , $row , $fd = ',' , $quot = '"' )
<
$str = '' ;
foreach ( $row as $cell ) <
$cell = str_replace (Array( $quot , "\n" ),
Array( $quot . $quot , '' ),
$cell );
if ( strchr ( $cell , $fd )!== FALSE || strchr ( $cell , $quot )!== FALSE ) <
$str .= $quot . $cell . $quot . $fd ;
> else <
$str .= $cell . $fd ;
>
>

I want to create a csv file, but when I run the code, it returns a blank page and no csv file. I use PHP 5. I use the following code:


5,384 5 5 gold badges 27 27 silver badges 40 40 bronze badges 773 1 1 gold badge 7 7 silver badges 9 9 bronze badges You are not echoing anything thus the page will be blank only. It will just create csv for you as per your code.

3 Answers 3

Its blank because you are writing to file . you should write to output using php://output instead and also send header information to indicate that it's csv.


48.7k 15 15 gold badges 104 104 silver badges 137 137 bronze badges


90.8k 28 28 gold badges 160 160 silver badges 213 213 bronze badges can i know how give the existing excel sheet path for this? I was having issues putting header() after fputcsv() and once I moved them above fputcsv() , I stopped having issues.

@Baba's answer is great. But you don't need to use explode because fputcsv takes an array as a parameter

For instance, if you have a three columns, four lines document, here's a more straight version:



4,165 4 4 gold badges 41 41 silver badges 50 50 bronze badges Definitely, that should work and even might be more appropriate. More details here

Just in case if someone is wondering to save the CSV file to a specific path for email attachments. Then it can be done as follows

I know I have added a lot of comments just for newbies :)

I have added an example so that you can summarize well.

NOTE: The following is a very bad idea to increase the memory_limit and time limit, but I have only added to make sure if anyone faces the problem of connection time out or any other. Make sure to find out some alternative before sticking to it.

Читайте также: