UTF-8编码的HTML页面显示问号(?)而不是字符

39
我在win7(x64)上安装了标准的XAMPP。在之前的一个项目中,我的MySQL编码与PHP编码不匹配,有时将HTML输出到其他编码导致了一些编码问题。因此,我决定使用UTF-8来一致地对所有内容进行编码。
我刚开始使用HTML标记就遇到了麻烦。
以下是一些设置:
- 我保存页面时使用UTF-8(没有BOM,我想) - 通过.htaccess文件设置php以UTF-8格式提供.php页面:AddCharset UTF-8 .php - HTML中有一个meta标签指定:<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> - 为了测试,我使用php设置header('Content-Type:text/html; charset=UTF-8');
页面显然是以utf-8格式提供的(firefox和chrome也能识别),但是任何特殊字符,如é、á或¡都只显示为�,在查看源代码时也是如此。
当删除上述编码设置时,所有字符都可以正确呈现,但是检测到的编码显示为windows-1252或ISO-8859-1,这取决于浏览器。
为什么会这样呢?我很困惑。我本应该期望相反的行为。
欢迎提出任何建议,谢谢!
HTTP/1.1 200 OK
Date: Sat, 26 Mar 2011 20:49:44 GMT
Server: Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1
X-Powered-By: PHP/5.3.1
Content-Length: 91
Keep-Alive: timeout=5, max=99
Connection: Keep-Alive
Content-Type: text/html; charset=utf-8
7个回答

27

当放弃上述编码设置时, 所有的字符都会被正确地显示, 但是检测到的编码会根据浏览器 显示为 windows-1252 或 ISO-8859-1。

那么你实际上发送的就是检测到的编码。你在目录中列出的编码设置不会对输出进行任何修改,它们只告诉浏览器在解释你发送的内容时应该采用什么编码格式。这就是为什么会出现 � 的原因——你告诉浏览器你发送的是 UTF-8 编码,但实际上是 ISO-8859-1 编码。


5
没错!你在告诉服务器说“charset=utf-8”,但实际情况并非如此。服务器和浏览器都是信任型的实体。服务器会说出你告诉它的任何内容,而浏览器会相信服务器关于编码的陈述——即使这不是真实情况。 - Sherm Pendley
2
非UTF-8数据的来源而言,从您在此处发布的内容中无法确定。如果简单的“echo(“föö”);”显示为f��,则可能表明您的.php文件保存为iso-8859-1。如果数据是从数据库中获取的,则可以使用mb_detect_encoding()来验证其编码。 - Sherm Pendley
4
你说得对,指出了真正的问题所在。谢谢!看起来文件没有保存为 utf-8,我不得不返回创建它的环境。在那里,在“项目设置”下隐藏着一个选项设置为“ISO-8859-1”。将此选项更改为“UTF-8”并再次保存文件即可获得所需的结果。无需设置 header(); 或修改apaches配置或 .htaccess 文件。这是一个愚蠢的错误,既令人恼火又令人满意。感谢你的回答和评论,Sherm! - leugim
@ShermPendley:您能否看一下这个链接(http://stackoverflow.com/questions/23212974/html-special-characters-converted-to-question-mark-in-chrome-mozilla),其中提问者在IE中可以正确显示字符,但在Chrome和Firefox中都无法正常显示。 - Nidheesh

16

在我的情况下,数据库返回了latin1,而我的浏览器期望utf8

所以对于MySQLi,我做了以下操作:

 mysqli_set_charset($dblink, "utf8");    

请查看http://php.net/manual/zh/mysqli.set-charset.php以获取更多信息。


1
你是个牛人,这才是最终为我解决问题的方法。谢谢兄弟! - Cesar Bielich

9
告诉PDO您的字符集初始设置...类似于以下内容。
PDO("mysql:host=$host;dbname=$DB_name;charset=utf8;", $username, $password);

注意: charset=utf8; 部分。
希望对您有所帮助!

7
检查您的任何打印文本的.php文件是否正确编码为utf-8

我不确定我是否理解正确,但是一个简单的 echo(é); 也会输出那个该死的问号。我已经在我的答案中更新了头信息。 - leugim
1
我的意思是,当您有一个基本的PHP文件(UTF-8),并将一些其他PHP文件包含到其中而没有良好的编码时。 - IProblemFactory
啊!好的,目前来说这是最简单的情况:一个带有简单echo和一些基本HTML标记的PHP文件,其中包含这些字符的文本。我还没有包括任何东西。除了提到的编码选项。 - leugim
1
有时候你会获取一个 .csv 文件,但文件本身的编码是错误的。打开这个 .csv 或其他基于文本的数据文件,选择适当的编码(Textmate 2 在打开时有预览模式),然后使用“另存为...”,选择“UTF-8”作为编码来制作一份副本。这样,在 php 5.3 及以上版本中问题就应该解决了。 - Christian Bonato

4

我来自巴西,创建我的数据库时使用的是latin1_spanish_ci。对于HTML和其他所有内容,我使用:

charset=ISO-8859-1

数据配合 éãç 正确传输... 有时我必须使用它的代码来放置 html 文本,比如:

Ol&aacute;

提供给我

Olá

您可以在这个页面找到代码:http://www.ascii.cl/htmlcodes.htm希望这有所帮助。我记得这非常烦人。

谢谢你的回答!我想找到一种不编码字符的方法。我考虑使用utf-8,因为我读到它包含了所有可能的字符...我可以通过切换到ISO-8859来解决这个问题,但我更愿意对此进行一些探讨。 - leugim
重新开始,使用最简单的配置,但不要开始用HTML转义字符。 - tetris

3

看起来没有人提到

SET NAMES utf8;

我在这里找到了一个解决方案(链接),它对我很有帮助。如何应用它:

在连接到数据库服务器后,请发出以下语句以使所有内容都是UTF-8: SET NAMES utf8;

也许这会对某些人有所帮助。


请参见:是否使用“SET NAMES” - hakre
感谢提供信息,抱歉回复晚了。我一直使用mysql_set_charset(),但有一个项目需要进行调整,不知何故这个函数无法正常工作。我尝试了各种其他方法(甚至修改了本地机器上的httpd.conf和php.ini),但只有SET NAMES utf8才帮助了我。 顺便说一句,现在不鼓励使用mysql_set_charset():http://php.net/manual/en/function.mysql-set-charset.php - Vitalius
是的,这取决于MySQL和PHP版本,所以这并不像今天这样直截了当。幸运的是,情况确实有所改善。 - hakre
这帮了我很多。我在这上面纠结了好几天。 - Zahari Kitanov

2
问题在于Apache用来提供页面的字符集。我使用Linux,所以对XAMPP一无所知。我也遇到了同样的问题,解决方法是将字符集添加到charset配置文件中(默认情况下被注释掉)。
在我的情况下,它在/etc/apache2/conf.d/charset中,但由于你使用的是Windows,所以位置可能不同。所以我给你这个作为解决方法的一个想法。
最后,我的字符集配置文件如下:
# Read the documentation before enabling AddDefaultCharset.
# In general, it is only a good idea if you know that all your files
# have this encoding. It will override any encoding given in the files
# in meta http-equiv or xml encoding tags.

AddDefaultCharset UTF-8

我希望这能有所帮助。

他已经做了那个 - 它是上面项目清单中的第二项。而且这也没有帮助; 如果你发送的是ISO-8859-1,则在HTTP头中指定“charset = utf-8”只会让浏览器混淆,导致它显示那些�s。 - Sherm Pendley

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