我有一个使用latin-1的数据库和一个utf-8的PHP应用程序。
我在数据库中有这样的字符串:
'Société'应该是Société
'â,11bn '应该是20亿欧元。
当我使用PHP的 ord()将错误字符打印到屏幕时,从数据库中返回的数据中打印195和226。
有人可以解释为什么会发生这种情况(为什么要像这样保存以及为什么要按原样读取字符)以及我是否可以撤消它。
答案 0 :(得分:5)
为什么:
1)é是unicode 233(浏览器读取它)
转换为latin1 chars字节的é
utf8字节为Ã ©
。这就是数据库中出现这种情况的原因
à ©
被识别为Ã
,这是代码点195.因此,为什么你会看到它。
2)€是unicode 8364
转换为latin1字节字节的€utf8字节为â <82> ¬
。这就是为什么它们在数据库中看起来像这样
â <82> ¬
被识别为â
,这是代码点226.这也是您看到这一点的原因。
这就是为什么你会看到来自ord()
的值以及为什么字符以这种方式存储在latin-1数据库中的原因。
<强>反向:强>
要反转它,我们需要Latin-1个字节到UTF8个字节。
如果我们尝试一下:
â
为226.将latin-1转换为utf8会产生â
Ã
为195.将latin-1转换为utf8会产生Ã
。
<强>问题:强>
问题是Latin-1的字符少于utf-8(很长一段时间)
Latin1单字节流和UTF8多字节字符串流,因此utf8中的1个字符可以为latin1生成最多4个字符。
因此,UTF-8到Latin-1的转换会产生错误的字符
拉丁文1回到utf8是不可能的。
<强>解决方案:强>
如果您无法更改数据库的字符集,我可以建议在编写数据库之前在其字符实体中编码特殊字符(因此数据库可以保留为latin1和app作为utf8,因为两者都可以理解html实体)例如变音符号为Ä
。
可以使用PHP html_entity_decode()
结合mb_detect_encoding()
来检测和转换特定字符。
<强>参考文献:强>
ltf.ed.ac.uk 请参阅 utf8字节到latin1字节:
http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=%C3%96&mode=char
答案 1 :(得分:0)
这些是UTF-8中的字符串,但显示为latin1。在UTF-8中é
和€
用两个字节编码,这就是当字符串被解释为latin1时你看到两个字符的原因。所以你要做的是将UTF-8数据存储在一个未声明为UTF-8的表中。您应该更改数据库*和连接**的编码,然后您将获得数据的一致表示
*)例如,请参阅此处:https://stackoverflow.com/a/6184788/664108(案例2 )
SQL中的 **)SET NAMES 'utf8'