我正在开发一个使用各种特殊字符的项目,目前我正在专门研究阿拉伯字符,我正在努力让它们在从 PHP 导出时正确显示在 Excel 中,使用我的代码原样显示为方括号在导出的文件中。
我尝试了许多不同的方法来实现这一点,有些方法比其他方法效果更好,但最终每次尝试都有某种形式的问题。
我做了一些研究,发现使用 BOM 编码为 UTF-16LE 是最有可能实现这一点的方法,但到目前为止,我无法弄清楚如何最好地实现这一点。
我试过的
您将能够在下面的代码中看到,根据我在代码开头设置的四个变量,代码可以采用几条路线,我开始放入这些切换按钮,以便我可以尝试不同的方法而无需编写我的代码不可读。
目前,使用我的代码中的设置,我可以导出 CSV,但阿拉伯字符显示为方框 - 当我在 VS Code 中查看 CSV 时,我可以看到它无法识别编码类型并且将默认为 UTF-8,它还会告诉我它已成功使用 BOM 导出。
切换到 UTF-16LE 似乎很简单,而且我实际上已经成功了,但是自从将其导出为 BOM 后,我一直无法弄清楚如何将其恢复为 UTF-16LE。最终,我认为我已经盯着代码太久了,我怀疑修复会很快,但我现在无法看到它,我希望通过在关于 SO 的问题中解释我的问题我能够弄清楚问题是什么,但到目前为止还没有。
我尝试导出为逗号分隔、制表符分隔、使用array_walk
,iconv
并将mb_convert_encode
值转换为 UTF-16LE,我尝试在标题中设置 Content-Encoding 和 Content-Type,使用\xEF\xBB\xBF
和chr(255) . chr(254)
在导出的开头转换为 BOM(下面的当前版本似乎效果最好)。
您还可以在我的代码中看到我同时使用了这两种方法fwrite
,并fputcsv
查看哪一种效果最好,fputcsv
目前似乎效果最好。
任何指针将不胜感激 - 任何需要澄清的问题请在评论中提出。
到目前为止我的代码
function convertToUTF16LE(&$value, $key) {
$value = iconv('UTF-8', 'UTF-16LE', $value);
}
$fput = true;
$iconv = true;
$UTF16 = true;
$walk = false;
if($UTF16 == true) {
header('Content-Encoding: UTF-16LE');
header('Content-type: text/csv; charset=UTF-16LE');
} else {
header('Content-Encoding: UTF-8');
header('Content-Type: text/csv; charset=UTF-8');
}
header('Content-Disposition: attachment; filename="file.csv"');
header("Content-Transfer-Encoding: binary");
header('Accept-Ranges: bytes');
header("Cache-control: private");
header('Pragma: private');
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
$filesize = 0;
$delimiter = '\t';
$prefix = '';
$output = fopen('php://output', 'w');
$headings = array("IATA Code", "Country", "Country Code", "English Name", "Current Name", "Is Primary?", "New Name");
if($UTF16 == true && $walk == true) array_walk($headings, 'convertToUTF16LE');
if($UTF16 == true) $prefix = "\xEF\xBB\xBF"; // chr(255) . chr(254);
$filesize += fwrite($output, $prefix . 'sep=' . $delimiter . PHP_EOL);
if($fput == true) {
$filesize += fputcsv($output, $headings, $delimiter, '"', "\0");
} else {
$headings_data = implode($delimiter, $headings);
$filesize += fwrite($output, $headings_data . PHP_EOL);
}
// This variable exists but the data has not been included in this code.
foreach($data_to_export as $row) {
foreach($row as $k => $v) {
if($UTF16 == true) $row[$k] = ($iconv == true ? iconv('UTF-8', 'UTF-16LE', $v) : mb_convert_encoding($v, 'UTF-16LE', 'auto'));
}
if($UTF16 == true && $walk == true) array_walk($row, 'convertToUTF16LE');
if($fput == true) {
$filesize += fputcsv($output, array(
$row['code'],
$row['country'],
$row['countrycode'],
$row['english_name'],
$row['name'],
($row['isprimary'] ? 'Y' : 'N'),
''
), $delimiter, '"', '\0');
} else {
$row_data = implode($delimiter, $row);
$filesize += fwrite($output, $row_data . PHP_EOL);
}
}
header("Content-Length: ".$filesize);
exit(0);