如何在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中我没有任何select“以UTF-8打开”,所以…我有点恼火。

尽pipe很多人遇到了同样的问题,但我似乎无法在任何地方find明确的解决scheme。 我看到最多的东西是包含BOM,但是我不能确切地知道如何做到这一点。 正如你可以看到上面我只是echo这个数据,我不写任何文件。 如果需要的话,我可以这样做,我只是不是因为在这一点上似乎不需要它。 任何帮助?

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

引用微软支持工程师的话 ,

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'); 
  2. 确保您添加了UTF-16LE字节顺序标记

     chr(255) . chr(254) 

下一个仅在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 Docs电子表格)与使用逗号的UTF-8文件没有任何问题。

请参阅此问题中的表格,了解Excel中的Unicode CSV文件有效和无效


作为一个侧面说明,我可以补充说,如果你使用的是Composer ,你应该看看如何添加League\Csv到你的需求。 League\Csv有一个非常好的API来build立CSV文件 。

要使用这种创buildCSV文件的方法使用League\Csv ,请查看此示例

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

在我的情况下,如果我添加一个物料清单到输出,它的工作原理:

 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 

我相信这是一个非常丑陋的黑客攻击,但它对我来说至less在Excel 2007 Windows中起作用。 不知道它会在Mac上工作。

这是我做的(这是提示浏览器下载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(); 

它唯一固定的UTF8编码问题的CSV预览,当你点击Mac上的空格键..但不是在Excel的Mac 2008 …不知道为什么

我刚刚解决了同样的问题,并提出了两个解决scheme。

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

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

       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; } 
  2. 由于PHPExcel的效率问题,我还必须弄清楚如何生成兼容UTF-8和Excel的CSV或TSV文件。

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

       header ( 'HTTP/1.1 200 OK' ); header ( 'Date: ' . date ( 'DM j G:i:s TY' ) ); header ( 'Last-Modified: ' . date ( 'DM j G:i:s TY' ) ); 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; 

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

 mb_convert_encoding($output, 'UCS-2LE', 'UTF-8'); 

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

  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(); 

为了跟进这一点:

看来,这个问题只是在Mac上使用Excel。 这不是我如何生成这些文件,因为即使从Excel生成CSV也会破坏它们。 我保存为CSV,并重新导入,所有的字符都搞砸了。

所以…似乎没有一个正确的答案。 感谢所有的build议。

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

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

或者按照build议和解决方法只是用HTTP身体回声

由于UTF8编码在Excel中不能很好地发挥作用。 您可以使用iconv()将数据转换为另一种编码types。

例如

 iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $value), 

加:

 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); 

正如我调查,我发现UTF-8在MAC和Windows上不能正常工作,所以我尝试使用Windows-1252,它支持两个,但你必须select在Ubuntu的编码types。 这里是我的代码$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 

如何输出Excel本身? 这是一个非常好的类 ,允许您在服务器端生成XLS文件。 我经常使用它的客户谁不能“弄清楚”csv的,迄今为止从来没有投诉。 它也允许一些额外的格式(阴影,rowheights,计算等),csv将永远不会做。

你可以转换你的CSVstring与iconv 。 例如:

 $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) ); 

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

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

也许你必须转换你的string:

 private function convertToWindowsCharset($string) { $encoding = mb_detect_encoding($string); return iconv($encoding, "Windows-1252", $string); } 

对于我来说,上述解决scheme都没有奏效。 以下是我所做的解决问题:在PHP代码中使用此function修改值:

 $value = utf8_encode($value); 

这个输出值在excel表格中正确。

这适用于Windows和Mac OS的excel。

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

 function writeCSV($fileprefix, $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; } 

当我有一个导入数据的Excel VBA例程时,我也遇到了同样的问题。 由于CSV是一种纯文本格式,我正在通过编程方式在一个简单的文件编辑器(如wordpad)中打开数据,并将其重新保存为unicode文本,或者将其复制到剪贴板并粘贴到Excel中来解决此问题。 如果excel不会自动将CSVparsing到单元格中,则可以使用内置的“文本到列”function轻松修复该问题。

当你把它保存为一个.txt文件时,问题是否仍然存在,并且在excel中用逗号作为分隔符打开它?

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

这个post是相当老,但经过几个小时的努力,我想分享我的解决scheme…也许它可以帮助某人处理Excel和Mac和CSV和绊倒这个威胁。 我正在用Excel用户的数据库dynamic生成一个csv。 (带BOM的UTF-8)

我尝试了很多iconv的,但不能得到在Mac Excel 2004中工作的德语变音。一个解决scheme:PHPExcel。 这是伟大的,但对我的项目有点太多了。 什么对我来说是创buildcsv文件,并将此csv文件转换为xls与此PHPsnippet: csv2xls 。 结果xls与excel德语变音器(ä,ö,Ü,…)合作。

我只是尝试这些标题,并在Windows 7 PC上获得Excel 2013以正确导入带有特殊字符的CSV文件。 字节顺序标记(BOM)是使其工作的最后一个关键。


    标题('Content-Encoding:UTF-8');
     header('Content-type:text / csv; charset = UTF-8');
     header(“Content-disposition:attachment; filename = filename.csv”);
    标题(“Pragma:public”);
    标题(“过期:0”);
    回声“\ xEF \ xBB \ xBF”;  // UTF-8 BOM

您可以在导出之前将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 EF BF BF)。 否则,Excel将根据您的语言环境的默认编码(例如cp1252)而不是utf-8解释数据

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

否则,您可以:

 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); 

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

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

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

EASY解决scheme为Mac Excel 2008:我努力了这个很多次,但这里是我的简单修复:打开Textwrangler中的.csv文件,它应该打开你的UTF-8字符正确。 现在在底部状态栏中将文件格式从“Unicode(UTF-8)”更改为“Western(ISO Latin 1)”并保存文件。 现在进入你的Mac Excel 2008,并select文件>导入>selectCSV>查找你的文件>在文件来源select“Windows(ANSI)”,瞧,UTF-8字符显示正确。 至less它对我来说…

我用这个,它的工作原理

 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; 

我在Mac上,在我的情况下,我只需要指定"sep=;\n"的分隔符和UTF-16LE这样的文件编码:

 $data = "sep=;\n" .mb_convert_encoding($data, 'UTF-16LE', 'UTF-8'); 

#在PHP中输出一个UTF-8 CSV,Excel将正确读取。

 //Use tab as field separator $sep = "\t"; $eol = "\n"; $fputcsv = count($headings) ? '"'. implode('"'.$sep.'"', $headings).'"'.$eol : ''; 
 //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"));