代码之家  ›  专栏  ›  技术社区  ›  Loftx

MySQL中的Unicode字符在PHP和ASP中返回不同的字符代码值

  •  1
  • Loftx  · 技术社区  · 15 年前

    我有一个mysql数据库,需要通过php和mysql脚本来访问,这在大多数情况下都很好,但是一些“特殊”字符(例如双引号、撇号)在asp脚本中不能正确显示。

    例如,MySQL数据库来自Drupal安装,包含一个表,其中的字段包含文本“双引号”(引号是智能引号,但似乎不会在堆栈溢出时显示)。这在PHP脚本中显示得很好,但不是ASP脚本。我在php和asp中编写了一个简单的脚本来循环字符串并打印字符代码,这里是输出:

    PHP

    “ 147
    A 65
    32
    d 100
    o 111
    u 117
    b 98
    l 108
    e 101
    32
    q 113
    u 117
    o 111
    t 116
    e 101
    ” 148
    

    ASP

    � 8220
    A 65
     32
    d 100
    o 111
    u 117
    b 98
    l 108
    e 101
     32
    q 113
    u 117
    o 111
    t 116
    e 101
    � 8221
    

    如您所见,在php和asp中,双引号是以不同的字符出现的,而asp引号的呈现不正确。

    我在一台Windows机器上运行MySQL5,使用标准的Drupal安装和PHP5。ASP使用mysql odbc 3.51驱动程序,除了打开连接并运行select语句外,我没有在php或asp中运行任何其他命令。

    编辑 根据要求,这里是ASP脚本

    Dim strConn, objConn, objRS, strQ
    Dim i, strBody
    
    strConn = "DRIVER={MySQL ODBC 3.51 Driver}; SERVER=" & strDBServer & "; DATABASE=studential; UID=" & strDBUser & ";PASSWORD=" & strDBPass & "; OPTION=3"
    
    Set objConn = Server.CreateObject("ADODB.Connection")     
    objConn.Open(strConn)
    
    strQ = "select body from drupal_node_revisions where nid = 261"
    Set objRS = objConn.Execute(strQ)
    
    strBody = objRS("body")
    
    For i = 1 To len(strBody)       
        Response.write(Mid(strBody, i, 1) & " " & AscW(Mid(strBody, i, 1))  & "<br />")
    Next
    
    objRS.Close
    objConn.Close
    
    Set objRS = Nothing
    Set objConn = Nothing
    

    进一步编辑

    用以下行中的asc替换ascw时:

    Response.write(Mid(strBody, i, 1) & " " & AscW(Mid(strBody, i, 1))  & "<br />")
    

    字符代码现在匹配,但引号字符仍然显示不正确。我的页面包含了utf-8字符集标记,所以它很可能是以前没有使用utf-8编码的东西——你知道它可能是什么或者我如何修复它吗?

    谢谢你的帮助,

    汤姆

    3 回复  |  直到 6 年前
        1
  •  0
  •   Paul Dixon    15 年前

    您的ASP脚本似乎使用的是Unicode-8220=0x201C,它是Unicode“左双引号”。您可能在屏幕上看到了垃圾,因为您的ASP脚本没有输出此Unicode字符串的有效编码,但我们必须看到代码来确定原因。

        2
  •  2
  •   MtnViewMark    15 年前

    这里似乎发生了几件事:

    我假设在数据库中,表drupal_node_revisions中的列体确实设置为Unicode字符集。此外,我假设它确实从代码点U+201C左双引号开始。

    现在,PHP似乎正在以拉丁语1连接到数据库。这会导致MySQL将正在读取的数据转换为Windows-1252(MySQL中的“Latin1”实际上意味着Windows-1252)。因此,将第一个字符转换为单字节147。然后,当您从PHP输出这个代码时,我猜想您没有指出网页的字符编码,这会导致它默认为Latin1,而Latin1(叹息)几乎所有浏览器都将其视为Windows-1252。因此,双引号显示正确,但实际上犯了两个错误,这将导致其他Unicode字符失败:

    1. 你需要执行 SET NAMES utf8; 在连接中,确保所有连接变量都指向MySQL(有三个!)正在使用UTF-8。

    2. 您需要确保网页的内容类型指示一个字符集utf-8。这可以通过一个元元素来实现: <meta http-equiv="content-type" content="text/html;charset=utf-8">

    ASP代码似乎正在以某种Unicode编码连接到数据库。这是独立的表达式 AscW(Mid(strBody, i, 1)) 返回8220作为第一个字符。在输出中,生成未知字符glyph的问题再次出现,HTML页面的字符集可能是默认的,而不是Unicode兼容的编码。

    我对ASP不太了解,不知道 Response.write() 方法确定要使用的字符集编码,或者它是否希望字符串已经被编码,因此我无法帮助确定如何确保数据路径是Unicode端到端的干净编码。

        3
  •  1
  •   avs099    6 年前

    我也有同样的问题。结果,列在 latin1_swedish_ci 排序规则-它使用扩展的ASCII符号(例如146用于 )-哪个.NET转换成Unicode符号- \u0092 -但这不是有效的代码。最终解决方案的灵感来自 this SO answer :

    res = Encoding.GetEncoding(1252).GetString(res.Select(c => (byte) c).ToArray());