PHP转换为MySql再转换为CSV,最后转换为Excel UTF-8

3
我知道这个问题已经被讨论了很多次,但是我处理这个问题的时候还是感到很困惑。我有一个表单,使用submit.php作为动作。起初,我没有改变字符集方面的任何内容,也没有使用任何utf8头信息...结果是,在数据库中,我可以正确读取所有的 ä,ö,ü等字符。但是,将它们导出到 .csv,并作为 UTF-8 字符集导入 Excel(也测试了其他所有字符集),结果却是字符集不正确。
现在我尝试了以下操作:
PHP:
header("Content-Type: text/html; charset=utf-8");
$mysqli->set_charset("utf8");

MySQL: 我删除了我的数据库并创建了一个新的:

create database db CHARACTER SET utf8 COLLATE utf8_general_ci;
create table ...

我修改了my.cnf并重新启动了我的SQL服务器:

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

[mysql]
default-character-set=utf8

如果我通过bash连接到我的数据库,会收到以下输出:

| character_set_client     | utf8                             |
| character_set_connection | utf8                             |
| character_set_database   | utf8                             |
| character_set_filesystem | binary                           |
| character_set_results    | utf8                             |
| character_set_server     | utf8                             |
| character_set_system     | utf8                             |
| character_sets_dir       | /usr/local/mysql/share/charsets/ |

一个PHP测试:

var_dump($mysqli->get_charset());

给我:
Current character set: utf8 object(stdClass)#3 (8) { ["charset"]=> string(4) "utf8"     ["collation"]=> string(15) "utf8_general_ci" ["dir"]=> string(0) "" ["min_length"]=> int(1) ["max_length"]=> int(3) ["number"]=> int(33) ["state"]=> int(1) ["comment"]=> string(13) "UTF-8 Unicode" }

现在我使用的是:

mysql -uroot -ppw db < require.sql > /tmp/test.csv

require.sql 简单来说就是一个

select * from table;

再次尝试将其作为 csv 导入到 Excel 中,无论我选择 UTF-8 还是其他编码都无法导入。它总是给我一些加密内容。

希望有人能够提供一些关于可能出错的提示。

谢谢

附注:TextMate 给出了正确的输出,因此转换实际上已经成功,这是 Excel 的问题吗?使用 Microsoft Office 2011。

另外,我也尝试了同样的事情,使用 latin1 - 相同的问题,无法在不破坏它们的情况下导入特殊字符到 Excel 中。有什么提示或解决方法吗?

我找到了一个解决方法,可以使用 Excel 导入功能工作,但不能通过双击 .csv 文件来实现。

    iconv -f utf8 -t ISO-8859-1 test.csv > test_ISO.csv

现在我可以使用Windows(ANSI)将csv导入Excel。仍然很烦人,因为需要使用此功能而不是双击。而且我真的不明白为什么UTF8不起作用,即使使用导入功能,添加BOM并将整个数据库设置为UTF8也不行。
逗号分隔也很混乱。 1. Concat_WS只部分起作用,因为它会在.csv文件中添加一个愚蠢的concat_ws(..)标头。此外,“file test.csv”没有给我“逗号分隔”。这意味着即使所有内容都用逗号分隔,Excel在双击时也无法识别它。 2. sed/awk:找到了一些代码片段,但它们都将表格分隔得非常糟糕。例如,列街道“街道名称编号”仍然是“街道名称”,“编号”,这样就从一个列中创建了两个列,表格就被搞砸了。
所以对我来说,Excel只能打开通过双击打开的.csv文件 a)编码为ISO-8859-1(仅限于Windows,因为标准Mac字符集是Macintosh) b)文件具有“逗号分隔”属性。这意味着如果我通过Excel本身创建.csv,则输出的...
file test1.csv

would be

test1.csv: ISO-8859 text, with CRLF line terminators

使用正则表达式添加逗号时更改字符集的Iconv可能如下所示:

test1.csv: ISO-8859 text

相当奇怪的行为 - 或许有人找到了解决方案。

1
Excel在编码方面非常糟糕!你是否在文本编辑器中打开CSV文件以查看它是否实际上是UTF-8?如果是正确的,使用Excel中的各种手动导入选项来正确地导入数据。否则,很有可能Excel是唯一的问题。 - deceze
OpenOffice也能正确输出,选择UTF-8。在Excel中,我有很多选项可供选择。我使用了Unicode 5.1(UTF-8),但也尝试了其他所有选项。由于我的客户正在使用Excel,我希望我的.csv文件能够正确显示。这真的很烦人。 - gulty
1
尝试向文件添加BOM(谷歌一下)。同样,Excel在编码方面非常糟糕。如果可能的话,使用好的第三方转换器将数据转换为.xls格式。Apple的Numbers对于初学者来说非常不错,OOo也可以。 - deceze
感谢您的努力,但添加BOM并没有任何区别。 - gulty
2个回答

0
这是我从utf-8 mysql表中保存数据的方法。 你需要先添加BOM。 例如:
<?php
$fp = fopen(dirname(__FILE__).'/'.$filename, 'wb'); 
fputs($fp, "\xEF\xBB\xBF"); 
fputcsv($fp, array($utfstr_1,$utfstr_2);
fclose($fp);

确保你也告诉MySQL你将使用UTF-8

mysql_query("SET CHARACTER SET utf8"); 
mysql_query("SET NAMES utf8"); 

在选择任何数据之前,您需要执行此操作。

如果设置区域设置:setlocale(LC_ALL, "en_US.UTF-8");可能不会有问题。

希望能帮到您。


抱歉,但它无法工作。我将 .csv 文件从 utf8 转换为 ISO-8859-1。我使用的是 Mac,如果我将其导入为 Windows(ANSI),似乎可以工作。不过不能通过双击文件打开。此外,逗号分隔符也无法识别。我使用了以下命令:mysql -uroot db_name -e 'select * from table' > name.csv 导出所有内容。尝试了几个正则表达式进行分离,但都没有起作用。Concat_WS 添加到了标题中。awk 将所有空格转换,sed 正则表达式总是在 "t" 字母处截断我的表格。由于我的列中有空格(街道名称 nr),所以什么都不起作用。 - gulty
我可以发送给您使用 PHP 制作的 CSV 文件,该文件保存了来自 MySQL 表的 UTF-8 数据。只是为了确保这是与 MacOS Office 相关的问题。 - KennyPowers
可以的话,如果您上传就太好了,因为我不知道在这里分享电子邮件:P提前谢谢。 - gulty
这就是我看到的:http://clip2net.com/clip/m13398/1359658398-clip-14kb.png。这是文件链接:https://dl.dropbox.com/u/27304306/mandarin_2012_12_27_17_00_00.csv。 - KennyPowers
请看这里,这是双击操作的截图:http://s1.directupload.net/images/130131/n374z64p.png。如您所见,它是以制表符分隔的。使用import utf-8可以得到这样的结果:http://s1.directupload.net/images/130131/sm5xlwm6.png。 - gulty
我一直在为你寻找答案,但除了许多人对Mac版Excel的抱怨外,什么都找不到。我的解决方案适用于Windows版本的Excel,但是对于MacOS :( 我不确定我还能帮你什么了,很抱歉。 - KennyPowers

0
感谢大家的帮助,我终于成功地创建了一个可双击打开的 CSV 文件,它能够正确地显示字母。 对于那些对良好工作流程感兴趣的人,以下是我的步骤:
1.) 我的数据库完全使用 UTF8。 2.) 我通过 PHP 将表单导出到我的数据库中。我使用 mysqli,并将其作为头信息:
header("Content-Type: text/html; charset=ISO-8859");

我知道这会让数据库中的所有内容看起来很糟糕,但是你可以随意使用utf8使其正确显示,但在我的情况下并不重要。

3.) 我编写了一个由cron守护程序执行的脚本,它 a) 删除以前创建的.csv文件

rm -f path/to/csv ##I have 3 due to some renaming see below
b) 使用 MySQL 创建新的 CSV 文件(仍为 UTF8 编码)
mysql -hSERVERIP -uUSER -pPASS DBNAME -e "select * from DBTABLE;" > PATH/TO/output.csv

现在你有一个以制表符分隔的 .csv 文件(如果你是从 PHP 中以 UTF8 导出的),它将在 OpenOffice 等软件中正确显示,但在 Excel 中不会。即使使用 UTF8 导入也无法正常工作。

c)将文件改为分号分隔(Excel 标准,双击逗号分隔的文件至少在欧洲版的 Excel 中不起作用)。我使用了一个小的 Python 脚本 semicolon.py:

import sys
import csv

tabin = csv.reader(sys.stdin, dialect=csv.excel_tab)
commaout = csv.writer(sys.stdout, delimiter=";")
for row in tabin:
  commaout.writerow(row)

d) 现在我需要在我的 cron sh 文件中调用脚本:

/usr/bin/python PATH/TO/semicolon.py < output.csv > output_semi.csv

如果将脚本用作 cron,请确保每个文件都使用完整路径。

e) 使用 iconv 将字符集从 UTF8 更改为 ISO-8859-1(Windows ANSI Excel 标准):

iconv -f utf8 -t ISO-8859-1 output_semi.csv > output_final.csv

就是这样。在Mac/Windows Excel 2010上双击csv文件即可打开(已测试)。

也许对于有类似问题的人会有所帮助。这让我疯狂了。

编辑:对于一些服务器,您不需要iconv,因为数据库输出已经是ISO8859格式的。在执行mysql命令后应检查您的csv文件。

file output.csv

只有在字符集不是iso8859-1时才使用iconv。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接