2010-04-01 98 views
19

我正在写一些评论的PHP类,我偶然发现了一个问题。我的名字(@author标记)以ș(这是一个UTF-8字符,...和一个奇怪的名字,我知道)结尾。PHP文件中的UTF-8 BOM签名

尽管我将文件保存为UTF-8,但有些朋友报告说他们看到该字符完全混乱(È™)。通过添加BOM签名可以消除此问题。但是这件事让我感到困扰,因为我对它的了解不多,除了我在维基百科上看到的以及其他类似的问题。

我知道它在文件的开头添加了一些东西,从我的理解中并没有那么糟糕,但是我担心,因为我读到的唯一有问题的场景涉及PHP文件。而且由于我正在编写PHP类来分享它们,100%兼容比在评论中注明我的名字更重要。

但我想了解其含义,我应该使用它而不用担心?或者是否有可能造成损害的情况?什么时候?

+0

需要注意的是,今天我在包含的PHP文件顶部的一个'<?php die('test')'显示文件顶部的UTF-8 BOM(这些字符:“?”)时出现问题。这很难弄清楚。那时我发现其中一位开发人员用Unicode保存了文件,而不是ASCII,而且这个PHP无法读取Unicoded PHP文件。我开始了一个新的复制,复制数据并保存在ASCII中,问题就解决了。请注意,如果您遇到过这种情况,某些FTP程序可以为您做到这一点。 – Volomike 2012-05-14 15:12:22

+0

另请注意,当页面出现此UTF-8 BOM表问题时,会话变量似乎无法在页面之间正常工作。我必须在Ubuntu上使用像ghex这样的十六进制编辑器,再加上'iconv -f utf8 -t ascii old.php> new.php'来检测所有的Unicode问题,将它们移除并最终以ASCII形式保存页面iconv命令。一旦完成,我注意到会话变量在页面之间保持状态。 – Volomike 2012-05-14 15:50:40

+0

看来,当在文件中检测到UTF-8 BOM时,永远不会发送用于保存会话的标头,因此页面之间的会话变量将获得全新的会话而不是保持相同的会话。 – Volomike 2012-05-14 16:00:38

回答

23

事实上,BOM是发送给浏览器的实际数据。浏览器会高兴地忽略它,但仍然无法发送标题。

我相信问题确实是你和你朋友的编辑器设置。没有BOM,你朋友的编辑器可能不会自动将文件识别为UTF-8。他可以尝试设置他的编辑器,以便编辑器预计文件使用UTF-8(如果您使用的是真正的IDE,例如NetBeans,那么这甚至可以作为项目设置,您可以随同码)。

另一种方法是尝试一些技巧:一些编辑尝试根据输入的文本使用一些启发式来确定编码。你可以尝试启动每个文件

<?php //Úτƒ-8 encoded 

也许启发式会得到它。有可能有更好的东西放在那里,你可以谷歌什么样的编码检测启发式是常见的,或者只是尝试一些:-)

总而言之,我建议只修复编辑器设置。噢,等等,我误解了最后一部分:为了将代码传播到任何地方,我猜你最安全的做法是让所有文件只包含较低的7位字符,即纯ASCII,或者只接受某些人与古代编辑看你的名字写得有趣。没有故障安全的方式。物料清单肯定是坏的,因为头已经发送了东西。另一方面,只要你在注释中只放置UTF-8字符,那么某些编辑器误解编码的唯一影响就是奇怪的字符。我会去正确拼写你的名字,并添加一个针对启发式的评论,这样大多数编辑都会得到它,但总会有人会看到假字符。

+2

+1修复编辑器设置。 – 2010-04-01 07:32:25

+0

感谢您的建议。我知道我的立场,我认为,而不是编码检测启发式,这是一种有点怪异的妥协,我会做出体面的选择,只是用“s”拼写我的名字而不是“ş”,大多数可能无论如何,编码人员甚至都没有使用他们的语言。对? :) – treznik 2010-04-01 14:39:50

+4

浏览器不会忽略BOM。而这些错误很难追踪。永远不要使用BOM保存PHP文件。 – hakre 2011-08-09 11:52:37

12

BOM会导致Headers already sent错误,因此,你不能在PHP文件使用BOM

+1

first + ve from me :) – 2014-03-26 16:46:19

1

或者你可以激活php.ini中的输出缓冲,这将解决“头已发送”的问题。如果您的站点负载很重,则使用输出缓冲来提高性能也非常重要。

8

这是一篇旧文章,已经得到解答,但我可以为您留下一些其他资源,这些资源是我在遇到此BOM问题时找到的。

http://people.w3.org/rishida/utils/bomtester/index.php在此页面您可以检查特定文件是否包含物料清单。

还有一个方便的脚本,用于输出当前目录中包含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东西

其后期的答案的选项,但我仍然希望它有帮助。 再见

+0

+1这是一个很棒的脚本! – 2013-07-09 09:26:43

+1

fopen_utf8()脚本帮助我从供应商使用的SDK中分离BOM文件。很有帮助! – 2014-01-27 18:10:50

6

大家知道,在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 
3

在PHP中,除了“头已经发送”错误,BOM表的存在,也搞砸了在浏览器的HTML更微妙的方式。

查看此link了解该问题的提纲。

发生这种情况时,不仅在渲染页面的顶部通常会有明显的空间,但如果您在Firefox或Chrome中检查HTML,则可能会注意到头部是空的,其元素看起来像是在身体里。当然,查看源代码会显示应该显示的所有内容,但不知何故浏览器会将其解释为错误。

0

BOM实际上是识别UTF-8文件的最有效方式,现代浏览器和标准都支持并鼓励在HTTP响应主体中使用它。

如果PHP文件不是文件,而是生成的输出作为响应发送,所以很显然,在开始时保存所有带有BOM的PHP文件并不是一个好主意,但这并不意味着您不应该“在您的回复中使用BOM。

你其实可以放心你的DOCTYPE声明前右注入下面的代码(如果您正在生成HTML的响应):

<?="\xEF\xBB\xBF"?>

如需进一步阅读:https://www.w3.org/International/questions/qa-byte-order-mark#transcoding