无法使用PHP对UTF8中的CSV文件进行编码

时间:2017-01-18 09:28:01

标签: php csv encoding utf-8

我一直在尝试使用PHP导出正确编码和格式化的CSV文件。但它只是不起作用。我已经在SOF上的每个CSV / PHP相关线程中尝试了每个提示,我已经检查过我的数据库中的数据是UTF-8,它是。我在整个CSV线上尝试过像utf8_encode()这样的东西,我检查过实际的PHP文件是用UTF-8编码的,但仍然没有成功。当我在http://csvlint.io/上运行文件时,我得到:

  

您的CSV似乎以ASCII-8BIT编码。我们建议您使用UTF-8。

但我无法在我的代码中的任何地方找到除UTF-8之外的任何其他编码的痕迹。 基本上这是我的代码:

首先,我将所有CSV行放在一个数组中,然后执行此操作:

if (count($array) == 0)
{
    return NULL;
}
ob_start();
$df = fopen("php://output", 'w');
$csv = utf8_encode("header1|header2|header3|header4|header5|header6|header7\r\n");
foreach($array as $line) {
    $csv .= $line . "\r\n";
}
setlocale(LC_ALL, 'sv_SE', "swedish");
fwrite($df, "\xEF\xBB\xBF".$csv);
fclose($df);
return ob_get_clean();

这些是发送的标题:

$now = gmdate("D, d M Y H:i:s");
header("Expires: Tue, 03 Jul 2001 06:00:00 GMT");
header("Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate");
header("Last-Modified: {$now} GMT");
header("Content-Encoding: UTF-8");
header("Content-Type: text/csv; charset=UTF-8");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Disposition: attachment;filename={$filename}");
header("Content-Transfer-Encoding: binary");

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

问题是您在此行的输出前面加byte-order mark

fwrite($df, "\xEF\xBB\xBF".$csv);

如果您将其更改为

fwrite($df, $csv);

您应该发现生成的文件验证正常(或者至少,验证者不会抱怨其编码)。

可以说这是验证器的问题,因为正如维基百科的文章所述,

  

Unicode标准允许使用UTF-8的BOM,但不要求或建议使用它。

我也建议你不要使用它,因为大多数软件似乎都不能识别字节顺序标记。但是,如果你必须或者你只是喜欢,你可以安全地忽略来自CSVLint的警告。

由于这显然不是问题,我接下来要看的是,数据是否是以UTF-8从数据库检索。 (我会接受你的话,你已经仔细检查过以确保数据是以UTF-8存储。)如果你正在使用MySQL,这将取决于关于数据库服务器的配置以及连接后可能发送数据库的任何选项。

PHP手册有a section on character sets and MySQL,关于将PHP和MySQL与UTF-8数据一起使用还有this helpful article。如果您使用的是其他数据库系统,则可能具有应检查的等效配置选项。

我能提出的其他建议就是你

  • setlocale循环中开始字符串连接之前,将调用移至脚本中的foreach更高位置。 (我不认为此设置会影响简单连接,但我不确定。)

  • 从您的输出中删除Content-Encoding标题,it is invalid当前正在使用的方式。

答案 1 :(得分:0)

尝试使用此代码:

$filename = 'csv/'.date('Y-m-d_H:i:s').'.csv';
$fp = fopen($filename, 'w');

foreach ($csvData as $fields) {
    fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF));
    fputcsv($fp, $fields, $delimiter = ';');
}

fclose($fp);