1

我正在开发一个使用各种特殊字符的项目,目前我正在专门研究阿拉伯字符,我正在努力让它们在从 PHP 导出时正确显示在 Excel 中,使用我的代码原样显示为方括号在导出的文件中。

我尝试了许多不同的方法来实现这一点,有些方法比其他方法效果更好,但最终每次尝试都有某种形式的问题。

我做了一些研究,发现使用 BOM 编码为 UTF-16LE 是最有可能实现这一点的方法,但到目前为止,我无法弄清楚如何最好地实现这一点。


我试过的

您将能够在下面的代码中看到,根据我在代码开头设置的四个变量,代码可以采用几条路线,我开始放入这些切换按钮,以便我可以尝试不同的方法而无需编写我的代码不可读。

目前,使用我的代码中的设置,我可以导出 CSV,但阿拉伯字符显示为方框 - 当我在 VS Code 中查看 CSV 时,我可以看到它无法识别编码类型并且将默认为 UTF-8,它还会告诉我它已成功使用 BOM 导出。

切换到 UTF-16LE 似乎很简单,而且我实际上已经成功了,但是自从将其导出为 BOM 后,我一直无法弄清楚如何将其恢复为 UTF-16LE。最终,我认为我已经盯着代码太久了,我怀疑修复会很快,但我现在无法看到它,我希望通过在关于 SO 的问题中解释我的问题我能够弄清楚问题是什么,但到目前为止还没有。

我尝试导出为逗号分隔、制表符分隔、使用array_walkiconv并将mb_convert_encode值转换为 UTF-16LE,我尝试在标题中设置 Content-Encoding 和 Content-Type,使用\xEF\xBB\xBFchr(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);
4

0 回答 0