如何在PHP中输出UTF-8 CSV,以便Excel正确读取?
我有一个非常简单的东西,只输出一些CSV格式的东西,但它必须是UTF-8。我在TextEdit、TextMate或Dreamweaver中打开这个文件,它会正确显示UTF-8字符,但如果我在Excel中打开它,它会做这种愚蠢的事情。以下是我在文件开头的内容:如何在PHP中输出UTF-8 CSV,以便Excel正确读取?,php,csv,utf-8,byte-order-mark,Php,Csv,Utf 8,Byte Order Mark,我有一个非常简单的东西,只输出一些CSV格式的东西,但它必须是UTF-8。我在TextEdit、TextMate或Dreamweaver中打开这个文件,它会正确显示UTF-8字符,但如果我在Excel中打开它,它会做这种愚蠢的事情。以下是我在文件开头的内容: header("content-type:application/csv;charset=UTF-8"); header("Content-Disposition:attachment;filename=\"CHS.csv\""); 除了
header("content-type:application/csv;charset=UTF-8");
header("Content-Disposition:attachment;filename=\"CHS.csv\"");
除了Excel(Mac,2008)不想正确导入之外,这一切似乎都达到了预期效果。Excel中没有选项可以让我“以UTF-8打开”或其他任何东西,所以…我有点恼火
我似乎在任何地方都找不到任何明确的解决方案,尽管很多人都有同样的问题。我看到的最多的是包含BOM表,但我不知道该怎么做。正如你在上面看到的,我只是echo
ing这个数据,我没有写任何文件。如果我需要的话,我可以这样做,我只是没有,因为在这一点上似乎没有必要。有什么帮助吗
更新:我尝试将BOM作为
echo包(“CCC”,0xef,0xbb,0xbf)进行回显代码>我刚从一个试图检测BOM的站点中提取。但是Excel在导入时只是将这三个字符附加到第一个单元格中,并且仍然会弄乱特殊字符。我在使用Excel VBA例程导入数据时也遇到了同样的问题。由于CSV是纯文本格式,我通过编程在一个简单的文件编辑器(如写字板)中打开数据,然后将其重新保存为unicode文本,或者将其复制到剪贴板并粘贴到Excel来解决这个问题。如果excel无法自动将CSV解析为单元格,则可以使用内置的“文本到列”功能轻松解决此问题。当您将其保存为.txt文件并在excel中以逗号作为分隔符打开该文件时,是否仍会出现此问题
问题可能根本不是编码,可能只是根据excel标准,该文件不是一个完美的CSV。只输出excel本身如何?这允许您在服务器端生成XLS文件。我经常为那些无法“理解”csv的客户使用它,到目前为止,他们从未收到过投诉。它还允许一些csv永远不会做的额外格式(着色、行高、计算等) 我也有同样(或类似)的问题
在我的情况下,如果向输出中添加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
我相信这是一个相当丑陋的黑客行为,但它对我有效,至少对Excel2007Windows有效。不确定它是否能在Mac上工作。要继续此操作:
问题似乎只是在于Mac上的Excel。这不是我生成文件的方式,因为即使从Excel生成CSV也会破坏它们。我保存为CSV,然后重新导入,所有字符都被弄乱了
所以…似乎没有一个正确的答案。谢谢你的建议
据我所知,@Daniel Magliola关于BOM的建议可能是其他计算机的最佳答案。但它仍然不能解决我的问题。我只是处理了同样的问题,并提出了两个解决方案
使用该类
- 使用这个类生成最广泛兼容的文件,我能够从UTF-8编码的数据生成一个文件,这些数据在Excel2008Mac、Excel2007Windows和Google文档中打开良好李>
- 使用PHPExcel的最大问题是速度慢且占用大量内存,这对于大小合理的文件来说不是问题,但是如果Excel/CSV文件有数百行或数千行,此库将无法使用李>
- 这里是一个PHP方法,它将获取一些TSV数据并将Excel文件输出到浏览器,请注意,它使用的是Excel 5 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;
}
由于PHPExcel的效率问题,我还必须找出如何生成与UTF-8和Excel兼容的CSV或TSV文件
- 我能想到的最好的是一个与Excel2008Mac和Excel2007PC兼容的文件,而不是谷歌文档,这对我的应用程序来说已经足够好了李>
- 我找到了具体的解决方案,但您也应该阅读,因为它解释了问题李>
- 以下是我使用的PHP代码,请注意,我使用的是tsv数据(制表符作为分隔符,而不是逗号):
我是这样做的(即提示浏览器下载csv文件):
当你在Mac上点击空格键时,它唯一修复了CSV预览中UTF8编码问题。。但不是在Excel Mac 2008中。。。不知道为什么CSV文件不包含字节顺序标记
或者,根据建议和解决方法,只需使用HTTP正文将其回显即可。您可以使用iconv将CSV字符串转换为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) );
Excel不支持UTF-8。您必须将UTF-8文本编码为UCS-2LE
mb_convert_encoding($output, 'UCS-2LE', 'UTF-8');
因为UTF8编码不能很好地与Excel配合使用。您可以使用iconv()
将数据转换为另一种编码类型
e、 g
您必须使用编码“Windows-1252”
header('Content-Encoding:Windows-1252');
标题('Content-type:text/csv;charset=Windows-1252');
标题(“内容处置:附件;文件名={$filename}”);
也许您必须转换字符串:
私有函数convertToWindowsCharset($string){
$encoding=mb_detect_encoding($string);
返回iconv($encoding,“Windows-1252”,$string);
}
这篇文章已经很老了,但经过几个小时的尝试,我想分享我的解决方案……也许它能帮助处理Excel、Mac和CSV的人,并在这个威胁面前绊倒。我将动态生成一个csv作为数据库的输出,并考虑Excel用户。(带BOM的UTF-8)
我尝试了很多iconv,但无法让德国UMLAUT在MacExcel2004中工作。一个解决方案:PHPExcel。它是
$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) );
mb_convert_encoding($output, 'UCS-2LE', 'UTF-8');
iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $value),
mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');
chr(255) . chr(254)
$field_cnt = count($fields);
$field_cnt = count($fields)-1;
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
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 );
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);
$newContent = chr(239) . chr(187) . chr(191) . $originalContent
//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"));
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();
fprintf($file, chr(0xEF).chr(0xBB).chr(0xBF));
fprintf($file, "\xEF\xBB\xBF");
<?php
$file = fopen( "file.csv", "w");
fprintf( $file, "\xEF\xBB\xBF");
fputcsv( $file, ["english", 122, "বাংলা"]);
fclose($file);
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;
$data = "sep=;\n" .mb_convert_encoding($data, 'UTF-16LE', 'UTF-8');
$value = utf8_encode($value);
//Use tab as field separator
$sep = "\t";
$eol = "\n";
$fputcsv = count($headings) ? '"'. implode('"'.$sep.'"', $headings).'"'.$eol : '';
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;
}
$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
$out = fopen('php://output', 'w');
fprintf($out, chr(0xEF).chr(0xBB).chr(0xBF));
fputcsv($out, $some_csv_strings);
**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;
}