我有一个非常简单的东西,它只是以 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
输入这些数据,而不是在写入任何文件。如果需要,我可以这样做,我只是不是因为在这一点上似乎不需要它。有什么帮助吗?
更新:我尝试将 BOM 回显为 echo pack("CCC", 0xef, 0xbb, 0xbf);
,这是我刚刚从试图检测 BOM 的站点中提取的。但是 Excel 只是在导入时将这三个字符附加到第一个单元格,并且仍然弄乱了特殊字符。
我有相同(或类似)的问题。
就我而言,如果我将 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
我相信这是一个非常丑陋的 hack,但它对我有用,至少对 Excel 2007 Windows 来说是这样。不确定它是否可以在 Mac 上运行。
引用 a Microsoft support engineer,
Excel for Mac 目前不支持 UTF-8
2017 年更新:Office 2016 之前的所有 Microsoft Excel for Mac 版本都是如此。较新的版本(来自 Office 365)现在支持 UTF-8。
为了输出 Windows 和 OS X 上的 Excel 都能成功读取的 UTF-8 内容,您需要做两件事:
确保将 UTF-8 CSV 文本转换为 UTF-16LE mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');确保将 UTF-16LE 字节顺序标记添加到文件 chr(255) 的开头。 chr(254)
仅在 OS X(而不是 Windows)上的 Excel 出现的下一个问题将是在查看具有逗号分隔值的 CSV 文件时,Excel 将仅呈现一行,并且所有文本与第一行中的逗号一起呈现。
避免这种情况的方法是使用制表符作为分隔值。
我使用了 this function from the PHP comments(使用制表符“\t”而不是逗号),它在 OS X 和 Windows Excel 上运行良好。
请注意,要解决以空列作为行尾的问题,我确实必须更改以下代码行:
$field_cnt = count($fields);
至
$field_cnt = count($fields)-1;
正如此页面上的其他一些评论所说,其他电子表格应用程序(如 OpenOffice Calc、Apple 自己的 Numbers 和 Google Doc 的电子表格)对带有逗号的 UTF-8 文件没有任何问题。
请参阅 the table in this question,了解哪些内容适用于 Excel 中的 Unicode CSV 文件,哪些内容不适用
作为旁注,我可能会补充一点,如果您正在使用 Composer,您应该看看将 League\Csv
添加到您的需求中。 League\Csv
有 a really nice API for building CSV files。
要将 League\Csv
与这种创建 CSV 文件的方法一起使用,请查看 this example
sep=;
或 sep=,
的行会告诉 Excel 如何分隔 CSV 并再次正确创建列。
"sep=,\n"
,然后在另一行添加数据,事情就会出现乱码。如果我在一行中完成所有操作($csv = chr(255) . chr(254) /* BOM */ . "sep=,\n" . mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');
),一切都很好。现在在 Mac 上一切看起来都很棒。我没有要测试的 Windows。
这是我的做法(即提示浏览器下载 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 中没有...不知道为什么
$outstream = fopen( "php://output", 'w' ); fputs( $outstream, "\xEF\xBB\xBF" ); foreach ( $export as $fields ) { fputcsv( $outstream, $fields ); } fclose( $outstream );
))
。
在我的情况下,以下工作非常好地使带有 UTF-8 字符的 CSV 文件在 Excel 中正确显示。
$out = fopen('php://output', 'w');
fprintf($out, chr(0xEF).chr(0xBB).chr(0xBF));
fputcsv($out, $some_csv_strings);
0xEF 0xBB 0xBF
BOM 标头将使 Excel 知道正确的编码。
fprintf($out, chr(0xEF).chr(0xBB).chr(0xBF));
<-- 这正是我所需要的。它就像一个魅力。
我刚刚处理了同样的问题,并提出了两个解决方案。
使用 bpeterson76 建议的 PHPExcel 类。使用此类生成最广泛兼容的文件,我能够从 UTF-8 编码数据生成一个文件,该文件在 Excel 2008 Mac、Excel 2007 Windows 和 Google Docs 中打开良好。使用 PHPExcel 的最大问题是速度慢且占用大量内存,这对于大小合理的文件来说不是问题,但如果您的 Excel/CSV 文件有数百或数千行,则该库将无法使用。这是一个 PHP 方法,它将获取一些 TSV 数据并将 Excel 文件输出到浏览器,注意它使用 Excel5 Writer,这意味着该文件应该与旧版本的 Excel 兼容,但我不再可以访问任何文件,所以我无法测试它们。函数 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 = 新 PHPExcel(); $objPHPExcel->setActiveSheetIndex(0); $sheet = $objPHPExcel->getActiveSheet(); $行 = '1'; $col = "A"; foreach($export_data as $row_cells) { if(!is_array($row_cells)) { 继续; } foreach($row_cells as $cell) { $sheet->setCellValue($col.$row, $cell); $col++; } $行 += 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');出口;由于 PHPExcel 的效率问题,我还必须弄清楚如何生成与 UTF-8 和 Excel 兼容的 CSV 或 TSV 文件。我能想到的最好的文件是与 Excel 2008 Mac 和 Excel 2007 PC 兼容的文件,但不兼容 Google Docs,这对于我的应用程序来说已经足够好了。我在这里找到了解决方案,特别是这个答案,但你也应该阅读接受的答案,因为它解释了问题。这是我使用的 PHP 代码,注意我使用的是 tsv 数据(制表符作为分隔符而不是逗号): header ( 'HTTP/1.1 200 OK' );标题('日期:'。日期('DM j G:i:s T Y')); header ('Last-Modified:' . date ('DM j G:i:s T Y')); header ('Content-Type: application/vnd.ms-excel') ;标头(“内容处置:附件;文件名=export.csv”);打印 chr(255) 。 chr(254)。 mb_convert_encoding($tsv_data, 'UTF-16LE', '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();
Excel 不支持 UTF-8。您必须将 UTF-8 文本编码为 UCS-2LE。
mb_convert_encoding($output, 'UCS-2LE', 'UTF-8');
要对此进行跟进:
看来问题出在 Mac 上的 Excel 上。这不是我生成文件的方式,因为即使从 Excel 生成 CSV 也会破坏它们。我保存为 CSV,然后重新导入,所有字符都搞砸了。
所以……似乎没有一个正确的答案。感谢所有的建议。
我想说,就我所读的所有内容而言,@Daniel Magliola 关于 BOM 的建议可能是其他计算机的最佳答案。但它仍然不能解决我的问题。
这适用于 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;
}
CSV 文件必须包含字节顺序标记。
或者按照建议和解决方法,只需使用 HTTP 正文回显它
添加:
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);
不需要使用 mb_convert_encoding
转换已经 utf-8 编码的文本。只需在原始内容前面添加三个字符:
$newContent = chr(239) . chr(187) . chr(191) . $originalContent
对我来说,这解决了 csv 文件中特殊字符的问题。
fputs
与 UTF-8 BOM 结合时,对我来说唯一的解决方案似乎是这个。
由于 UTF8 编码不能很好地与 Excel 配合使用。您可以使用 iconv()
将数据转换为另一种编码类型。
例如
iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $value),
**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;
}
您可以使用 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) );
正如我所调查的那样,我发现 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
您必须使用编码“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);
}
您可以在导出之前将 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 来解释数据
Generating CSV file for Excel, how to have a newline inside a value
我在 Mac 上,在我的情况下,我只需要使用 "sep=;\n"
指定分隔符并像这样在 UTF-16LE 中对文件进行编码:
$data = "sep=;\n" .mb_convert_encoding($data, 'UTF-16LE', 'UTF-8');
对我来说,上述解决方案均无效。以下是我为解决问题所做的工作:在 PHP 代码中使用此函数修改值:
$value = utf8_encode($value);
此输出值在 excel 表中正确输出。
当我有一个导入数据的 Excel VBA 例程时,我遇到了同样的问题。由于 CSV 是纯文本格式,因此我通过编程方式在写字板等简单文件编辑器中打开数据,然后将其重新保存为 unicode 文本,或者从那里将其复制到剪贴板并将其粘贴到 Excel 中来解决这个问题。如果 excel 没有自动将 CSV 解析为单元格,则可以使用内置的“文本到列”功能轻松解决此问题。
当您将其保存为 .txt 文件并使用逗号作为分隔符在 excel 中打开该文件时,问题是否仍然存在?
问题可能根本不是编码,它可能只是根据 excel 标准该文件不是完美的 CSV。
我刚刚尝试了这些标题,并在 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
Mac Excel 2008 的简单解决方案:我为此苦苦挣扎了很多次,但这是我的简单解决方法:在 Textwrangler 中打开 .csv 文件,它应该正确打开你的 UTF-8 字符。现在在底部状态栏中将文件格式从“Unicode (UTF-8)”更改为“Western (ISO Latin 1)”并保存文件。现在转到您的 Mac Excel 2008 并选择 File > Import > Select csv > Find your file > 在 File origin 中选择“Windows (ANSI)”,瞧,UTF-8 字符显示正确。至少对我有用...
我使用它并且它有效
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;
不定期副业成功案例分享
Content-Encoding
标头来告诉字符集。这与压缩有关:developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…