我正在编写一些评论过的PHP类,我偶然发现了一个问题。我的名字(对于@author标签)以ș
(这是一个UTF-8字符,......和一个奇怪的名字,我知道)结束。
即使我将文件保存为UTF-8,一些朋友报告说他们看到这个角色完全搞砸了(È™
)。添加BOM签名会消除此问题。但是这件事让我感到很麻烦,因为我不太了解它,除了我在维基百科上看到的以及其他一些类似的问题。
我知道它在文件的开头添加了一些东西,从我的理解它并没有那么糟糕,但我很担心,因为我读到的唯一有问题的场景涉及PHP文件。因为我正在编写PHP类来共享它们,所以100%兼容比在评论中使用我的名字更重要。
但是我试图理解其含义,我应该使用它而不用担心吗?或者是否有可能造成损害的情况?当α
答案 0 :(得分:24)
实际上,BOM是发送到浏览器的实际数据。浏览器会很乐意忽略它,但是你仍然无法发送标题。
我认为问题确实是你和你朋友的编辑器设置。如果没有BOM,您朋友的编辑器可能无法自动将文件识别为UTF-8。他可以尝试设置他的编辑器,使编辑器期望一个文件是UTF-8(如果你使用真正的IDE,如NetBeans,那么这甚至可以成为你的项目设置可以随代码一起转移。)
另一种方法是尝试一些技巧:一些编辑器尝试使用基于输入文本的一些启发式来确定编码。您可以尝试使用
启动每个文件<?php //Úτƒ-8 encoded
也许启发式会得到它。可能有更好的东西放在那里,你可以google什么样的编码检测启发式常见,或只是尝试一些: - )
总而言之,我建议只修改编辑器设置。
哦等等,我误读了最后一部分:为了将代码传播到任何地方,我猜你最安全的只是让所有文件只包含较低的7位字符,即纯ASCII,或只是接受一些人古代编辑看到你的名字写得好笑。没有故障安全方式。由于已经发送了标题,因此BOM肯定是糟糕的。另一方面,只要你只在注释中放入UTF-8字符等,一些编辑误解编码的唯一影响就是奇怪的字符。我会正确拼写你的名字并添加针对启发式的评论,这样大多数编辑都会得到它,但总会有人会看到伪造的字符。
答案 1 :(得分:13)
BOM会导致Headers already sent
错误,因此,您无法在PHP文件中使用BOM
答案 2 :(得分:9)
这是一篇旧帖子,已经得到了解答,但我可以留下一些我在面对此BOM问题时找到的其他资源。
使用此页面http://people.w3.org/rishida/utils/bomtester/index.php,您可以检查特定文件是否包含BOM。
还有一个方便的脚本,可以在当前目录中输出所有带有BOM的文件。
<?php
function fopen_utf8 ($filename) {
$file = @fopen($filename, "r");
$bom = fread($file, 3);
if ($bom != b"\xEF\xBB\xBF")
{
return false;
}
else
{
return true;
}
}
function file_array($path, $exclude = ".|..|design", $recursive = true) {
$path = rtrim($path, "/") . "/";
$folder_handle = opendir($path);
$exclude_array = explode("|", $exclude);
$result = array();
while(false !== ($filename = readdir($folder_handle))) {
if(!in_array(strtolower($filename), $exclude_array)) {
if(is_dir($path . $filename . "/")) {
// Need to include full "path" or it's an infinite loop
if($recursive) $result[] = file_array($path . $filename . "/", $exclude, true);
} else {
if ( fopen_utf8($path . $filename) )
{
//$result[] = $filename;
echo ($path . $filename . "<br>");
}
}
}
}
return $result;
}
$files = file_array(".");
?>
我在php.net上找到了代码
Dreamweaver也对此有所帮助,它为您提供了保存文件的选项,而不包括BOM内容
这是一个迟到的答案,但我仍然希望它有所帮助。 再见
答案 3 :(得分:7)
您也知道,php zend.multibyte
中有一个选项,允许php使用BOM读取文件而不会出现Headers already sent
错误。
来自php.ini文件:
; If enabled, scripts may be written in encodings that are incompatible with
; the scanner. CP936, Big5, CP949 and Shift_JIS are the examples of such
; encodings. To use this feature, mbstring extension must be enabled.
; Default: Off
;zend.multibyte = Off
答案 4 :(得分:2)
或者您可以在php.ini中激活输出缓冲,这将解决“已发送标头”问题。如果您的站点负载很重,则使用输出缓冲来提高性能也非常重要。
答案 5 :(得分:2)
在PHP中,除了“已发送标头”错误之外,BOM的存在还会以更微妙的方式搞砸浏览器中的HTML。
有关问题的概述,请参阅此link。
发生这种情况时,不仅渲染页面的顶部通常会有明显的空间,而且如果您在Firefox或Chrome中检查HTML,您可能会注意到head部分为空,其元素似乎在身体。当然,查看源将显示它应该在哪里,但不知何故浏览器正在解释它错误。
答案 6 :(得分:1)
BOM实际上是识别UTF-8文件的最有效方式,现代浏览器和标准都支持并鼓励在HTTP响应体中使用它。
如果是PHP文件,它不是文件,而是生成的输出作为响应发送,所以显然在开头用BOM保存所有PHP文件不是一个好主意,但这并不意味着你不应该在回复中使用BOM。
事实上,您可以在doctype声明之前安全地注入以下代码(如果您生成HTML作为响应):
<?="\xEF\xBB\xBF"?>
进一步阅读:https://www.w3.org/International/questions/qa-byte-order-mark#transcoding
答案 7 :(得分:0)
添加到@omabena 答案使用此代码从您的文件中定位和删除 bom。请务必先备份您的文件以防万一。
function fopen_utf8 ($filename) {
$file = @fopen($filename, "r");
$bom = fread($file, 3);
if ($bom != b"\xEF\xBB\xBF")
{
return false;
}
else
{
return true;
}
}
function file_array($path, $exclude = ".|..|design", $recursive = true) {
$path = rtrim($path, "/") . "/";
$folder_handle = opendir($path);
$exclude_array = explode("|", $exclude);
$result = array();
while(false !== ($filename = readdir($folder_handle))) {
if(!in_array(strtolower($filename), $exclude_array)) {
if(is_dir($path . $filename . "/")) {
// Need to include full "path" or it's an infinite loop
if($recursive) $result[] = file_array($path . $filename . "/", $exclude, true);
} else {
if ( fopen_utf8($path . $filename) )
{
//$result[] = $filename;
echo ($path . $filename . "<br>");
$pathname = $path . $filename; // change the pathname to your target file(s) which you want to remove the BOM.
$file_handler = fopen($pathname, "r");
$contents = fread($file_handler, filesize($pathname));
fclose($file_handler);
for ($i = 0; $i < 3; $i++){
$bytes[$i] = ord(substr($contents, $i, 1));
}
if ($bytes[0] == 0xef && $bytes[1] == 0xbb && $bytes[2] == 0xbf){
$file_handler = fopen($pathname, "w");
fwrite($file_handler, substr($contents, 3));
fclose($file_handler);
printf("%s BOM removed.<br/>n", $pathname);
}
}
}
}
}
return $result;
}
$files = file_array(".");