CSV - кодировки, импорт и экспорт
· 2 мин. чтения
Comma Separated Values - типичный способ экспорта табличных данных, но далеко не стандартный в плане совместимости между Excel, php и другими источниками данных. Надо читать RFC, и пробовать всё на практике
Самое наглядное - если вы думали что данные достаточно через запятую перечислить, то если вы сохраните простой текстовый файл с такими данными:
ID,name 1,Mac'duck
То в Excel получите
Тому несколько причин
- Отсутсвие utf8
- Разные символы разделения данных (табы вместо запятых)
- Особые символы (", n , r) должны очищаться что-бы не побить линейную разметку
- fgetcsv()
- Данные лучше помещать в двойные кавычки, а сами двойные кавычки в данных эскейпятся повторением:
$value = str_replace('"', '""', $value);
$value = '"' . $value . '"' . ",";
Mysql
SELECT id, name, email INTO OUTFILE '/tmp/result.csv'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY 'n'
FROM users WHERE 1
Экспорт
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: public');
header('Content-Description: File Transfer');
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename=SomeFile_' .time(). '.csv;');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.strlen($strCSV));
mb_internal_encoding("UTF-8");
$strCSV= chr(255) . chr(254) . mb_convert_encoding($strCSV, "UTF-16LE", "UTF-8");
Импорт
uiyi
$sCSVFileData = file_get_contents($aFile['tmp_name']);
if (mb_detect_encoding($sCSVFileData)) {
$sCSVFileData = mb_convert_encoding(mb_substr($sCSVFileData, 2, mb_strlen($sCSVFileData)), "UTF-8", mb_detect_encoding($sCSVFileData));
}
else {
$sCSVFileData = mb_convert_encoding(mb_substr($sCSVFileData, 2, mb_strlen($sCSVFileData)), "UTF-8", "UTF-16LE");
}
$aCSVLines = explode("rn", $sCSVFileData);
for ($i = 0; $i < count($aCSVLines); $i++) {
if ($i > 0) {
$arrData[] = getCSVValues($aCSVLines[$i], "t");
}
}
function getCSVValues($sString, $sSeparator = ",") {
$sString = str_replace('""', "'", $sString);
$aBits = explode($sSeparator, $sString);
$aElements = array();
for ($i = 0; $i < count($aBits); $i++) {
if (($i % 2) == 1) {
$aElements[] = $aBits[$i];
}
else {
$sRest = $aBits[$i];
$sRest = preg_replace("/^" . $sSeparator . "/", "", $sRest);
$sRest = preg_replace("/" . $sSeparator . "$/", "", $sRest);
$aElements = array_merge($aElements, explode($sSeparator, $sRest));
}
}
return $aElements;
}