【问题标题】:SQL -> CSV (utf8-BOM header not working correctly)SQL -> CSV(utf8-BOM 标头无法正常工作)
【发布时间】:2014-04-18 11:34:55
【问题描述】:

我正在使用下面的代码将我的 MySQL 数据导出到 .CSV 文件中。一切正常,但是当我尝试导出这些字母ě, š, č, ř, ž, ý, á, í, é(捷克语字母)时,字母ě, ř, č 被导出为?。其他字母导出正常。

你能帮我解决这个问题吗?

<?php
/*******EDIT LINES 3-8*******/
$DB_Server    = "xxx";                          //MySQL Server    
$DB_Username  = "xxx";                          //MySQL Username     
$DB_Password  = "xxx";                          //MySQL Password     
$DB_DBName    = "xxx";                          //MySQL Database Name  
$DB_TBLName   = "wp_comments";                           //MySQL Table Name
$DB_Query     = "comment_author, comment_content";       //MySQL Query (what to select from db, you can use * for all)
$filename     = "excelfilename";                         //File Name
$filename_columns = array("Autor", "Content");           //File Name of columns
/*******YOU DO NOT NEED TO EDIT ANYTHING BELOW THIS LINE*******/ 

//headers
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Description: File Transfer');
header('Content-Encoding: UTF-8');
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename='.$filename.'.csv;');
header('Content-Transfer-Encoding: binary');  

//create MySQL connection  
mysql_connect($DB_Server,$DB_Username,$DB_Password);
mysql_select_db($DB_DBName);
$sql = "SELECT $DB_Query FROM $DB_TBLName";
$result = mysql_query($sql);

$fh = fopen('php://output', 'w');   
$fp = fwrite($fh, $bom =( chr(0xEF) . chr(0xBB) . chr(0xBF) )); // Write UTF-8 BOM
if($fp)
{
    fwrite($fh, "sep=\t" . PHP_EOL);   // Hint for MS Excel
    while($row = mysql_fetch_row($result)) {
        fputcsv($fh, $row, "\t");
    }
}
fclose($fh); 

【问题讨论】:

标签: php mysql csv


【解决方案1】:

由于您没有明确设置encoding of the database connection,因此将使用编译libmysql 的默认编码(通常是latin1)。在将结果集转码为该字符集时,MySQL 将其无法表示的任何字符替换为 ?

为避免这种情况,您应该在打开数据库连接后调用mysql_set_charset('utf8') — 请参阅UTF-8 all the way through

也就是说,您根本不应该使用 ext/mysql:它现在已被弃用,并且该手册已包含近三年来禁止在新代码中使用它的警告。请考虑使用MySQLiPDO

最后,如果 MySQL 服务器与 PHP 在同一台机器上,并且您拥有 FILE 权限,为什么不完全避免将数据交给 PHP,而直接使用 MySQL 的 SELECT ... INTO OUTFILE 命令生成输出文件?

//create MySQL connection  
$DB_DSN = "mysql:host=$DB_Server;dbname=$DB_DBName;charset=utf8";
new PDO($DB_DSN, $DB_Username, $DB_Password)->exec("
  SELECT $DB_Query
  INTO OUTFILE '/tmp/$filename.tsv'
  CHARACTER SET utf8
  FROM $DB_TBLName
");

echo "\xef\xbb\xbf"       // Write UTF-8 BOM
   , "sep=\t", PHP_EOL;   // Hint for MS Excel

readfile("/tmp/$filename.tsv");

请注意,您可能需要确保临时文件未被并发进程使用。

PS:当字段分隔符为逗号字符时,该格式才称为CSV(“逗号分隔值”);当使用制表符作为字段分隔符时,格式更正确地称为 TSV(“制表符分隔值”)并且应该具有 .tsv.tab 扩展名。

【讨论】:

  • 我不能在我的虚拟主机中使用这个解决方案INTO OUTFILE
  • @pes502:上述答案提供的不仅仅是一个解决方案。第二段特别说明了如何解决当前的尝试。
【解决方案2】:

虽然PHP documentation 不建议这样做,但您可以尝试使用“旧方式”通过 SQL 设置连接字符集:SET NAMES utf8;,然后在您选择数据库之后再使用SET CHARACTER SET utf8;

注意:这两个语句的顺序很重要!

编辑#1

我刚刚注意到,在 eggyal 的回答中,您遇到的唯一问题是缺少 INTO OUTFILE 权限。您应该尝试使用eggyal第二段中描述的方法,即在选择数据库后立即使用the mysql_set_charset('utf8')

【讨论】:

    猜你喜欢
    • 2018-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-30
    • 2013-09-16
    相关资源
    最近更新 更多