如何在PHP中输出UTF-8 CSV,Excel将正确读取?

我有一个非常简单的事情,只输出一些CSV格式的东西,但它必须是UTF-8。 我在TextEdit或TextMate或Dreamweaver中打开这个文件,它正确地显示了UTF-8字符,但是如果我在Excel中打开它,它就是这样做的傻事。 这是我在文档的头部所得到的:

header("content-type:application/csv;charset=UTF-8");
header("Content-Disposition:attachment;filename=\"CHS.csv\"");

除了Excel(Mac,2008)不想正确导入它之外,这一切似乎都具有预期的效果。 Excel中没有选项可以“以UTF-8打开”或其他任何东西,所以......我有点恼火。

尽管有很多人遇到同样的问题,我似乎无法在任何地方找到任何明确的解决方案。 我最看重的是包含BOM,但我无法弄清楚如何做到这一点。 正如你在上面看到的那样,这只是echo pack("CCC", 0xef, 0xbb, 0xbf);这个数据,我不是在写任何文件。 如果我需要,我可以这样做,我不是因为此时似乎不需要它。 有帮助吗?

更新:我尝试将BOM回显为echo pack("CCC", 0xef, 0xbb, 0xbf);,我刚刚从试图检测BOM的站点中提取。 但Excel只会在导入时将这三个字符附加到第一个单元格,并且仍会混淆特殊字符。

Ben Saufley asked 2019-04-19T06:08:43Z
30个解决方案
255 votes

我有同样(或类似)的问题。

在我的例子中,如果我将BOM添加到输出中,它可以工作:

header('Content-Encoding: UTF-8');
header('Content-type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename=Customers_Export.csv');
echo "\xEF\xBB\xBF"; // UTF-8 BOM

我相信这是一个非常难看的黑客,但它对我有用,至少对于Excel 2007 Windows。 不确定它是否适用于Mac。

Daniel Magliola answered 2019-04-19T06:11:27Z
110 votes

引用Microsoft支持工程师的话

Excel for Mac目前不支持UTF-8

更新,2017年:在Office 2016之前,所有版本的Microsoft Excel for Mac都适用。较新的版本(来自Office 365)现在支持UTF-8。

为了输出Windows和OS X上的Excel能够成功读取的UTF-8内容,您需要做两件事:

  1. 确保将UTF-8文本转换为UTF-16LE

    League\Csv
  2. 确保添加UTF-16LE字节顺序标记

    League\Csv

仅在OS X(但不是Windows)上使用Excel时出现的下一个问题是,当使用逗号分隔值查看CSV文件时,Excel将仅使用一行和所有文本以及第一行中的逗号呈现行。

避免这种情况的方法是使用制表符作为分隔值。

我在PHP注释中使用了这个函数(使用标签“\ t”而不是逗号),它在OS X和Windows Excel上运行得很好。

请注意,要修复空列作为行尾的问题,我必须更改代码行:

    $field_cnt = count($fields);

    $field_cnt = count($fields)-1;

正如本页上的其他一些评论所说,其他电子表格应用程序,如OpenOffice Calc,Apple自己的Numbers和Google Doc的电子表格,使用逗号的UTF-8文件都没有问题。

请参阅此问题中的表格,了解Excel中Unicode CSV文件的作用和不起作用


作为旁注,我可以补充一点,如果您使用的是Composer,您应该看一下将League\Csv添加到您的要求中。 League\Csv有一个非常好的用于构建CSV文件的API。

要使用此方法创建CSV文件,请使用League\Csv,请查看此示例

Tim Groeneveld answered 2019-04-19T06:10:47Z
30 votes

我是这样做的(这是为了提示浏览器下载csv文件):

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');
echo "\xEF\xBB\xBF"; // UTF-8 BOM
echo $csv_file_content;
exit();

当您点击Mac上的空格键时,它唯一能修复CSV预览中的UTF8编码问题..但不是在Excel Mac 2008中...不知道为什么

Jazzer answered 2019-04-19T06:11:59Z
22 votes

我刚刚处理了同样的问题,并提出了两个解决方案。

  1. 按照bpeterson76的建议使用PHPExcel类。

    • 使用此类生成最广泛的兼容文件,我能够生成UTF-8编码数据的文件,该文件在Excel 2008 Mac,Excel 2007 Windows和Google Docs中打开正常。
    • 使用PHPExcel的最大问题是速度慢且使用大量内存,这对于合理大小的文件来说不是问题,但如果您的Excel / CSV文件有数百或数千行,则此库将无法使用。
    • 这是一个PHP方法,它将获取一些TSV数据并将Excel文件输出到浏览器,请注意它使用Excel5 Writer,这意味着该文件应该与旧版本的Excel兼容,但我不再有任何访问权限, 所以我无法测试它们。

      header ( 'HTTP/1.1 200 OK' );
      header ( 'Date: ' . date ( 'D M j G:i:s T Y' ) );
      header ( 'Last-Modified: ' . date ( 'D M j G:i:s T Y' ) );
      header ( 'Content-Type: application/vnd.ms-excel') ;
      header ( 'Content-Disposition: attachment;filename=export.csv' );
      print chr(255) . chr(254) . mb_convert_encoding($tsv_data, 'UTF-16LE', 'UTF-8');
      exit;
      
  2. 由于PHPExcel的效率问题,我还必须弄清楚如何生成UTF-8& Excel兼容的CSV或TSV文件。

    • 我能想到的最好的是一个与Excel 2008 Mac和Excel 2007 PC兼容的文件,但不是Google Docs,这对我的应用程序来说已经足够了。
    • 我在这里找到了解决方案,特别是这个答案,但你也应该阅读接受的答案,因为它解释了问题。
    • 这是我使用的PHP代码,请注意我使用tsv数据(制表符作为分隔符而不是逗号):

      header ( 'HTTP/1.1 200 OK' );
      header ( 'Date: ' . date ( 'D M j G:i:s T Y' ) );
      header ( 'Last-Modified: ' . date ( 'D M j G:i:s T Y' ) );
      header ( 'Content-Type: application/vnd.ms-excel') ;
      header ( 'Content-Disposition: attachment;filename=export.csv' );
      print chr(255) . chr(254) . mb_convert_encoding($tsv_data, 'UTF-16LE', 'UTF-8');
      exit;
      
Jasdeep Gosal answered 2019-04-19T06:13:36Z
12 votes

Excel不支持UTF-8。 您必须将UTF-8文本编码为UCS-2LE。

mb_convert_encoding($output, 'UCS-2LE', 'UTF-8');
Leopold Gault answered 2019-04-19T06:14:01Z
12 votes

我有同样的问题,它解决如下:

    header('Content-Encoding: UTF-8');
    header('Content-Type: text/csv; charset=utf-8' );
    header(sprintf( 'Content-Disposition: attachment; filename=my-csv-%s.csv', date( 'dmY-His' ) ) );
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');

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

    //This line is important:
    fputs( $df, "\xEF\xBB\xBF" ); // UTF-8 BOM !!!!!

    foreach ( $rows as $row ) {
        fputcsv( $df, $row );
    }
    fclose($df);
    exit();
Reza Mamun answered 2019-04-19T06:14:27Z
8 votes

要跟进这个:

似乎问题只是Mac上的Excel。 这不是我生成文件的方式,因为即使从Excel生成CSV也会破坏它们。 我保存为CSV,并重新导入,所有字符都搞砸了。

所以...似乎没有正确答案。 感谢所有的建议。

我会说,从我读过的所有内容来看,@ Daniel Magliola关于BOM的建议可能是其他计算机的最佳答案。 但它仍然无法解决我的问题。

Ben Saufley answered 2019-04-19T06:15:14Z
6 votes

CSV文件集包括字节顺序标记。

或者根据建议和解决方法,只需使用HTTP正文回显它

Cybot answered 2019-04-19T06:15:46Z
5 votes

这适用于Windows和Mac OS的Excel。

修复excel中未显示包含变音符号,西里尔字母,希腊字母和货币符号的字符的问题。

function writeCSV($filename, $headings, $data) {   

    //Use tab as field separator
    $newTab  = "\t";
    $newLine  = "\n";

    $fputcsv  =  count($headings) ? '"'. implode('"'.$newTab.'"', $headings).'"'.$newLine : '';

    // Loop over the * to export
    if (! empty($data)) {
      foreach($data as $item) {
        $fputcsv .= '"'. implode('"'.$newTab.'"', $item).'"'.$newLine;
      }
    }

    //Convert CSV to UTF-16
    $encoded_csv = mb_convert_encoding($fputcsv, 'UTF-16LE', 'UTF-8');

    // Output CSV-specific headers
    header('Set-Cookie: fileDownload=true; path=/'); //This cookie is needed in order to trigger the success window.
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private",false);
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"$filename.csv\";" );
    header("Content-Transfer-Encoding: binary");
    header('Content-Length: '. strlen($encoded_csv));
    echo chr(255) . chr(254) . $encoded_csv; //php array convert to csv/excel

    exit;
}
Murali Krishna answered 2019-04-19T06:16:21Z
4 votes

由于UTF8编码与Excel不兼容。 您可以使用iconv()将数据转换为其他编码类型。

例如

iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $value),
Abrar A. Shareef answered 2019-04-19T06:16:52Z
4 votes

加:

fprintf($file, chr(0xEF).chr(0xBB).chr(0xBF));

要么:

fprintf($file, "\xEF\xBB\xBF");

在将任何内容写入CSV文件之前。

例:

<?php
$file = fopen( "file.csv", "w");
fprintf( $file, "\xEF\xBB\xBF");
fputcsv( $file, ["english", 122, "বাংলা"]);
fclose($file);
Rejaul answered 2019-04-19T06:17:24Z
4 votes

在我的情况下,以下工作非常好用于在Excel中正确显示UTF-8字符的CSV文件。

$out = fopen('php://output', 'w');
fprintf($out, chr(0xEF).chr(0xBB).chr(0xBF));
fputcsv($out, $some_csv_strings);

物料清单头0xEF 0xBB 0xBF将让Excel知道正确的编码。

Codemole answered 2019-04-19T06:17:58Z
2 votes

正如我调查的那样,我发现UTF-8在MAC和Windows上运行不佳,所以我尝试使用Windows-1252,它支持两者,但你必须在ubuntu上选择编码类型。这是我的代码$valueToWrite = mb_convert_encoding($value, 'Windows-1252');

$response->headers->set('Content-Type', $mime . '; charset=Windows-1252');
    $response->headers->set('Pragma', 'public');
    $response->headers->set('Content-Endcoding','Windows-1252');
    $response->headers->set('Cache-Control', 'maxage=1');
    $response->headers->set('Content-Disposition', $dispositionHeader);
    echo "\xEF\xBB\xBF"; // UTF-8 BOM
Ho Ha answered 2019-04-19T06:18:24Z
1 votes

如何只输出Excel本身? 这是一个很好的类,允许您在服务器端生成XLS文件。 我经常使用它为那些无法“弄清楚”csv的客户,到目前为止从未有过投诉。 它还允许一些csv永远不会做的额外格式化(阴影,行高,计算等)。

bpeterson76 answered 2019-04-19T06:18:50Z
1 votes

你可以用iconv转换你的CSV字符串。  例如:

$csvString = "Möckmühl;in Möckmühl ist die Hölle los\n";
file_put_contents('path/newTest.csv',iconv("UTF-8", "ISO-8859-1//TRANSLIT",$csvString) );
foued611 answered 2019-04-19T06:19:17Z
1 votes

您必须使用编码“Windows-1252”。

header('Content-Encoding: Windows-1252');
header('Content-type: text/csv; charset=Windows-1252');
header("Content-Disposition: attachment; filename={$filename}");

也许你必须转换你的字符串:

private function convertToWindowsCharset($string) {
  $encoding = mb_detect_encoding($string);

  return iconv($encoding, "Windows-1252", $string);
}
roNn23 answered 2019-04-19T06:19:49Z
1 votes

我在Mac上,在我的情况下,我只需要使用"sep=;\n"指定分隔符,并将此文件编码为UTF-16LE,如下所示:

$data = "sep=;\n" .mb_convert_encoding($data, 'UTF-16LE', 'UTF-8');
Sebastien Horin answered 2019-04-19T06:20:15Z
1 votes

对我来说,上述解决方案都没有奏效。 以下是我为解决此问题所做的工作:在PHP代码中使用此函数修改值:

$value = utf8_encode($value);

此输出值在Excel工作表中正确显示。

Barani r answered 2019-04-19T06:20:50Z
1 votes
**This is 100% works fine in excel for both Windows7,8,10 and also All Mac OS.**
//Fix issues in excel that are not displaying characters containing diacritics, cyrillic letters, Greek letter and currency symbols.

function generateCSVFile($filename, $headings, $data) {

    //Use tab as field separator
    $newTab  = "\t";
    $newLine  = "\n";

    $fputcsv  =  count($headings) ? '"'. implode('"'.$newTab.'"', $headings).'"'.$newLine : '';

    // Loop over the * to export
    if (! empty($data)) {
      foreach($data as $item) {
        $fputcsv .= '"'. implode('"'.$newTab.'"', $item).'"'.$newLine;
      }
    }

    //Convert CSV to UTF-16
    $encoded_csv = mb_convert_encoding($fputcsv, 'UTF-16LE', 'UTF-8');

    // Output CSV-specific headers
    header('Set-Cookie: fileDownload=true; path=/'); //This cookie is needed in order to trigger the success window.
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private",false);
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"$filename.csv\";" );
    header("Content-Transfer-Encoding: binary");
    header('Content-Length: '. strlen($encoded_csv));
    echo chr(255) . chr(254) . $encoded_csv; //php array convert to csv/excel
    exit;
}
Sagar72427 answered 2019-04-19T06:21:10Z
0 votes

当我有一个导入数据的Excel VBA例程时,我遇到了同样的问题。 由于CSV是纯文本格式,我通过在wordpad等简单文件编辑器中以编程方式打开数据,并将其作为unicode文本重新保存,或者从那里将其复制到剪贴板并将其粘贴到Excel中来解决这个问题。 如果excel不会自动将CSV解析为单元格,则可以使用内置的“Text to Columns”功能轻松解决此问题。

Alain answered 2019-04-19T06:21:37Z
0 votes

当您将其另存为.txt文件时,问题是否仍然存在,并且在excel中使用逗号作为分隔符打开它?

问题可能根本不是编码,根据excel标准,可能只是文件不是完美的CSV。

Alain answered 2019-04-19T06:22:12Z
0 votes

这篇文章很老了,但是经过几个小时的尝试后我想分享我的解决方案......也许它可以帮助处理Excel,Mac和CSV的人,并对这个威胁进行绊倒。 我正在动态地生成一个csv作为数据库的输出,考虑到Excel用户。 (带BOM的UTF-8)

我尝试了很多iconv但却无法在Mac Excel 2004中使用德语变音符号。一个解决方案:PHPExcel。 这很棒但是我的项目有点太多了。 对我有用的是创建csv文件并使用此PHPsnippet将此csv文件转换为xls:csv2xls。 结果xls适用于excel德语变音符号(ä,ö,Ü,...)。

t Book answered 2019-04-19T06:22:48Z
0 votes

我刚试过这些标题并在Windows 7 PC上安装了Excel 2013,以正确导入带有特殊字符的CSV文件。 字节顺序标记(BOM)是使其工作的最终密钥。

    header('Content-Encoding: UTF-8');
    header('Content-type: text/csv; charset=UTF-8');
    header("Content-disposition: attachment; filename=filename.csv");
    header("Pragma: public");
    header("Expires: 0");
    echo "\xEF\xBB\xBF"; // UTF-8 BOM

Brian answered 2019-04-19T06:23:16Z
0 votes

您可以在导出之前将3个字节附加到文件中,它适用于我。 在此之前,系统仅在Windows和HP -UX中工作,但在Linux中失败。

FileOutputStream fStream = new FileOutputStream( f );
final byte[] bom = new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF };
OutputStreamWriter writer = new OutputStreamWriter( fStream, "UTF8" );
fStream.write( bom );

在文件的开头有一个UTF-8 BOM(3个字节,十六进制EF BB BF)。 否则,Excel将根据您的区域设置的默认编码(例如cp1252)而不是utf-8来解释数据

为Excel生成CSV文件,如何在值中包含换行符

Cherry Yap answered 2019-04-19T06:23:57Z
0 votes

否则你可以:

header("Content-type: application/x-download");
header("Content-Transfer-Encoding: binary");
header("Content-disposition: attachment; filename=".$fileName."");
header("Cache-control: private");

echo utf8_decode($output);
user3519396 answered 2019-04-19T06:24:24Z
0 votes

不需要使用mb_convert_encoding转换已经utf-8编码的文本。 只需在原始内容前添加三个字符:

$newContent = chr(239) . chr(187) . chr(191) . $originalContent

对我来说,这解决了csv文件中特殊字符的问题。

Rvanlaak answered 2019-04-19T06:24:58Z
0 votes

适用于Mac Excel 2008的简便解决方案:我多次与这个soo挣扎,但这是我的简单修复:在Textwrangler中打开.csv文件,它应该正确打开你的UTF-8字符。 现在在底部状态栏中将文件格式从“Unicode(UTF-8)”更改为“Western(ISO Latin 1)”并保存文件。现在转到Mac Excel 2008并选择文件&gt; 导入&gt; 选择csv&gt; 找到您的文件&gt; 在文件来源中选择“Windows(ANSI)”并且正确显示UTF-8字符。 至少它对我有用......

Poul answered 2019-04-19T06:25:25Z
0 votes

我用它,它的工作原理

header('Content-Description: File Transfer');
header('Content-Type: text/csv; charset=UTF-16LE');
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 headers so that the file is downloaded rather than displayed
// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');
fputs( $output, "\xEF\xBB\xBF" );
// output the column headings
fputcsv($output, array('Thông tin khách hàng đăng ký'));
// fetch the data
$setutf8 = "SET NAMES utf8";
$q = $conn->query($setutf8);
$setutf8c = "SET character_set_results = 'utf8', character_set_client =
'utf8', character_set_connection = 'utf8', character_set_database = 'utf8',
character_set_server = 'utf8'";
$qc = $conn->query($setutf8c);
$setutf9 = "SET CHARACTER SET utf8";
$q1 = $conn->query($setutf9);
$setutf7 = "SET COLLATION_CONNECTION = 'utf8_general_ci'";
$q2 = $conn->query($setutf7);
$sql = "SELECT id, name, email FROM myguests";
$rows = $conn->query($sql);
$arr1= array();
if ($rows->num_rows > 0) {
// output data of each row
while($row = $rows->fetch_assoc()) {
    $rcontent = " Name: " . $row["name"]. " - Email: " . $row["email"];  
    $arr1[]["title"] =  $rcontent;
}
} else {
     echo "0 results";
}
$conn->close();
// loop over the rows, outputting them
foreach($arr1 as $result1):
   fputcsv($output, $result1);
endforeach;
BoRnbeBaD answered 2019-04-19T06:25:52Z
0 votes

#output PHP中的UTF-8 CSV,Excel将正确读取。

//Use tab as field separator   
$sep  = "\t";  
$eol  = "\n";    
$fputcsv  =  count($headings) ? '"'. implode('"'.$sep.'"', $headings).'"'.$eol : '';
Murali Krishna answered 2019-04-19T06:26:19Z
-1 votes
//convert UTF-8 file without BOM to UTF-16LE for excel on mac
$fileUtf8String = file_get_contents("file.ext");
file_put_contents("file.ext", "\xFF\xFE" . mb_convert_encoding($fileUtf8String, "UTF-16LE", "UTF-8"));
b3wii answered 2019-04-19T06:26:39Z
translate from https://stackoverflow.com:/questions/4348802/how-can-i-output-a-utf-8-csv-in-php-that-excel-will-read-properly