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

Ben*_*ley 181 php csv byte-order-mark utf-8

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

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

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

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

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

Dan*_*ola 272

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

在我的例子中,如果我将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
Run Code Online (Sandbox Code Playgroud)

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

  • 丑陋,但超级有帮助.谢谢. (10认同)
  • 不幸的是,我很确定这在OS X上根本不起作用.我认为它可能会在您导入时显示BOM(警告:朦胧的回忆.) (7认同)
  • 我一直在收到关于这个问题的警报,因为显然很多其他人偶然发现了这个问题.我希望我能够将此标记为正确,因为它已被大量投票.不幸的是,我终于给了这个解决方案一个镜头(很久以前放弃了这个项目),它在Excel 2008 for Mac中不适用于我.很高兴它为你工作.我赞成了解决方案.但它并没有解决Excel for Mac 2008的问题.如果有人在Mac上运气,绝对让我(显然*每个人*)知道. (4认同)
  • 这是对的.至少,我已经尝试过使用BOM,就像上面的例子一样,但它确实只是在开头显示了一些时髦的字符并且继续显示特殊的字符错误(在Excel 2011中测试).在所有设置中,这似乎对我最有用:http://stackoverflow.com/a/1648671/1005334(使用PHP). (2认同)
  • 我认为不应使用“Content-Encoding”标头来告诉字符集。这与压缩有关:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding (2认同)

Tim*_*eld 132

引述微软技术支持工程师,

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

    mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');
    
    Run Code Online (Sandbox Code Playgroud)
  2. 确保添加UTF-16LE字节顺序标记

    chr(255) . chr(254)
    
    Run Code Online (Sandbox Code Playgroud)

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

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

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

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

    $field_cnt = count($fields);
Run Code Online (Sandbox Code Playgroud)

    $field_cnt = count($fields)-1;
Run Code Online (Sandbox Code Playgroud)

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

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


作为旁注,我可以补充说,如果您使用的是Composer,您应该看看是否League\Csv需要添加.League\Csv一个非常好的API来构建CSV文件.

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

  • 我发现,如果我将字符串作为BOM开始,那么事情就会出现乱码,然后在另一行添加了"sep =,\n",然后在另一行添加了数据.如果我在一行中完成所有事情就很好(`$ csv = chr(255).chr(254)/*BOM*/."sep =,\n".mb_convert_encoding($ csv,'UTF-16LE', 'UTF-8');`).现在Mac上的一切看起来都很棒.我没有Windows测试. (5认同)
  • 说我笨,但我做不到。我使用 mb_convert_encoding 函数转换了我的数据并输出了文件内容前面的 BOM,但是当我在 Excel 中打开文件时,我只得到一行汉字。我现在仍在使用逗号而不是制表符,但大概这不应该导致我所看到的。 (2认同)
  • 此解决方案还解决了我在Mac和Windows上的UTF8问题.我还发现在CSV文件中添加一行`sep =;`或`sep =,`告诉Excel如何分离CSV并再次正确创建列. (2认同)
  • 唯一对我有用的东西.微软的不一致永远不会让我感到惊讶.保存正常的csv文件使用","作为分隔符,但如果由于某种原因使用"\ t"保存BOM..csv中的C代表"COMMA"该死的.这真的不难做到. (2认同)

Jaz*_*zer 30

我是这样做的(这是为了提示浏览器下载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();
Run Code Online (Sandbox Code Playgroud)

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

  • 我正在寻找一种直接输出到浏览器的方法,当我看到这篇文章时,这是我的解决方案,这篇文章包括BOM和二进制传输标题.`$ outstream = fopen("php:// output",'w'); fputs($ outstream,"\ xEF\xBB\xBF"); foreach($ export as $ fields){fputcsv($ outstream,$ fields); } fclose($ outstream);` (5认同)

小智 22

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

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

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

      function excel_export($tsv_data, $filename) {
          $export_data = preg_split("/\n/", $tsv_data);
          foreach($export_data as &$row) {
              $row = preg_split("/\t/", $row);
          }
      
          include("includes/PHPExcel.php");
          include('includes/PHPExcel/Writer/Excel5.php');
      
          $objPHPExcel = new PHPExcel();          
      
          $objPHPExcel->setActiveSheetIndex(0);
          $sheet = $objPHPExcel->getActiveSheet();
          $row = '1';
          $col = "A";
          foreach($export_data as $row_cells) {
              if(!is_array($row_cells)) { continue; }
                  foreach($row_cells as $cell) {
                      $sheet->setCellValue($col.$row, $cell);
                      $col++;
                  }
              $row += 1;
              $col = "A";
          }
      
          $objWriter = new PHPExcel_Writer_Excel5($objPHPExcel);
          header('Content-Type: application/vnd.ms-excel');
          header('Content-Disposition: attachment;filename="'.$filename.'.xls"');
          header('Cache-Control: max-age=0');
          $objWriter->save('php://output');   
          exit;   
      }
      
      Run Code Online (Sandbox Code Playgroud)
  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;
      
      Run Code Online (Sandbox Code Playgroud)


Rez*_*mun 13

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

    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();
Run Code Online (Sandbox Code Playgroud)


Leo*_*ult 12

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

mb_convert_encoding($output, 'UCS-2LE', 'UTF-8');
Run Code Online (Sandbox Code Playgroud)

  • 如上所述,更好地使用UTF-16LE,它涵盖了现有的每个角色. (3认同)

Ben*_*ley 8

要跟进这个:

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

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

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


Cod*_*ole 8

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

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

0xEF 0xBB 0xBFBOM头将让Excel知道正确的编码.

  • 为你加油,兄弟 <3 (4认同)

Mur*_*hna 7

这适用于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;
}
Run Code Online (Sandbox Code Playgroud)


Cyb*_*bot 6

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

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


Rej*_*aul 6

添加:

fprintf($file, chr(0xEF).chr(0xBB).chr(0xBF));
Run Code Online (Sandbox Code Playgroud)

或者:

fprintf($file, "\xEF\xBB\xBF");
Run Code Online (Sandbox Code Playgroud)

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

例子:

<?php
$file = fopen( "file.csv", "w");
fprintf( $file, "\xEF\xBB\xBF");
fputcsv( $file, ["english", 122, "?????"]);
fclose($file);
Run Code Online (Sandbox Code Playgroud)


小智 5

由于 UTF8 编码不能很好地与 Excel 配合使用。您可以使用 将数据转换为另一种编码类型iconv()

例如

iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $value),
Run Code Online (Sandbox Code Playgroud)


Rva*_*aak 5

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

$newContent = chr(239) . chr(187) . chr(191) . $originalContent
Run Code Online (Sandbox Code Playgroud)

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