有什么办法可以缓解使用PHP的Excel的UTF-8处理?

我已经从几个脚本中通过CSV文件导入和导出信息到数据库中,特别是Excel处理它们的方式,有一些非常奇怪的UTF-8行为。

脚本本身不是特别复杂,我相信我正确设置编码(为了简洁起见,我已经排除了error handling和字符转义代码):

import

header("Content-Type: text/plain; charset=UTF-8"); require_once("inc.db.php"); // database connection mysql_query("SET NAMES utf8"); $csv = $_FILES['csv']; $handle = fopen($csv['tmp_name'], "r"); while ($data = fgetcsv($handle, 1000, ',', '"')) { $first_name = $data[0]; $family_name = $data[1]; $company = $data[2]; mysql_query("INSERT INTO table SET first_name = '$first_name', etc...); } 

出口

 header("Content-Type: text/csv; charset=UTF-8"); header("Content-Disposition: attachment; filename=file.csv"); header("Pragma: no-cache"); header("Expires: 0"); echo "\xEF\xBB\xBF"); // utf-8 bom setlocale(LC_ALL, "en_US.UTF8"); require_once("inc.db.php"); // database connection mysql_query("SET NAMES utf8"); echo "FIRST NAME,FAMILY NAME,COMPANY,\n"; $query = mysql_query("SELECT first_name, family_name, company FROM table"); while ($data = mysql_fetch_assoc($query)) { echo '"' . $first_name . '","' . $family_name. '","' . $company. '",\n'; } // Alternate attempt at looping below $array = array(); while ($data = mysql_fetch_assoc($query)) { $array[] = $data; } $x = fopen("php://output", "w"); foreach ($array as $fields) { fputcsv($x, $fields); } fclose($x); 

在我看来,这两个脚本工作正常,迄今没有问题。 但是,当我在Excel中打开并处理导出的CSV文件时,这是有趣的东西开始的地方。

数据库中的信息包含外部拉丁字符,如éÜ 。 这些存储正确(MySQL数据库编码是utf8_unicode_ci ),仍然没有问题。

但是,三种scheme中只有两种正常工作。 但是猜猜怎么样,那个不工作的人(情​​景二)是我需要工作的那个……是不是总是这样?


情景一

我导出一个CSV文件,然后立即重新导入。 我从不以任何方式打开或修改文件。

不幸的是,这是一个毫无意义的练习。 它确实有效,但是。


情景二

我导出一个CSV文件,打开它,修改内容,保存,然后重新导入。

有趣的是:当我从Excel的对话菜单中select“保存”时,它将保存为“Unicode文本”文件而不是覆盖CSV文件。 这个新文件仍然在Excel中打开,但数据已损坏。 我需要select“另存为…”并从文件types菜单中select“逗号分隔值”。 我也尝试从这一步的编码菜单中selectUTF-8。

这种情况下的问题在于外部字符:只要导入脚本到达其中一个脚本,它就会停止将该字段写入数据库。 没有损坏的字符“。 没有小问号 。 根本没有 但是,CSV的那一行中的其余数据是正确的。


情景三

我导出一个CSV文件,打开它,修改内容,保存,在文本编辑器中打开,用UTF-8编码重新保存,然后重新导入。

万岁,它的作品! 不过,我不能指望这个系统的用户玩文本编辑器和编码 – 他们应该能够导出>编辑>保存>无缝导入。


我对“错在哪里”的思考

  1. 在我的一个脚本中的东西(可能是导入)不能正确处理编码。
  2. 我的一个脚本中的某些内容(可能是导出)不能正确地创build一个CSV文件,因此保存对话框中的Unicode文本文件types。
  3. Excel只是真的不喜欢UTF-8文件,没有什么我可以做的。

请告诉我,这里的错在于我,而且我有办法解决这个问题!

在Windows Excel中,“ Unicode Text另存为”选项会写出一个制表符分隔的Unicode文件,但是Windows就是这样,将其写入UTF16中。 您的导入可能预期UTF-8,所以一旦它碰到奇数字节的2字节UTF-16LE编码的外来字符,就会自动放弃并放弃。

您可以使用linux命令iconv -f UTF-16LE -t utf8 yourfile.address > yourfile.address.tmp进行转换,或将您的导入脚本更改为接受UTF-16LE编码的数据。