Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP文件中的UTF-8 BOM签名_Php_Utf 8_Character Encoding_Byte Order Mark - Fatal编程技术网

PHP文件中的UTF-8 BOM签名

PHP文件中的UTF-8 BOM签名,php,utf-8,character-encoding,byte-order-mark,Php,Utf 8,Character Encoding,Byte Order Mark,我在写一些有注释的PHP类时,偶然发现了一个问题。我的名字(对于@author标签)以ș结尾(这是一个UTF-8字符,…我知道是个奇怪的名字) 尽管我将文件保存为UTF-8,但一些朋友报告说,他们看到的字符完全乱七八糟(È™)。通过添加BOM签名,可以解决此问题。但这件事让我有点困扰,因为除了我在维基百科和其他类似问题上看到的以外,我对它了解不多 我知道它在文件的开头添加了一些东西,据我所知,这并没有那么糟糕,但我很担心,因为我读到的唯一有问题的场景涉及到PHP文件。由于我编写PHP类是为了共享

我在写一些有注释的PHP类时,偶然发现了一个问题。我的名字(对于@author标签)以
ș
结尾(这是一个UTF-8字符,…我知道是个奇怪的名字)

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

我知道它在文件的开头添加了一些东西,据我所知,这并没有那么糟糕,但我很担心,因为我读到的唯一有问题的场景涉及到PHP文件。由于我编写PHP类是为了共享它们,所以100%兼容比在评论中留下我的名字更重要


但我正在努力理解其中的含义,我应该不用担心就使用它吗?或者有可能造成损害的情况吗?当?

BOM将导致已发送的
标题出现错误时,您不能在PHP文件中使用BOM。事实上,BOM是发送到浏览器的实际数据。浏览器会很高兴地忽略它,但仍然无法发送标题

我相信问题真的是你和你朋友的编辑器设置。如果没有BOM表,朋友的编辑器可能无法自动将文件识别为UTF-8。他可以尝试设置编辑器,使编辑器期望文件为UTF-8格式(如果使用真正的IDE,如NetBeans,则甚至可以将其设置为项目设置,以便与代码一起传输)

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

<?php //Úτƒ-8 encoded

或者您可以在php.ini中激活输出缓冲,这将解决“已发送的标题”问题。如果您的站点有大量负载,那么使用输出缓冲来提高性能也是非常重要的。

这是一篇老文章,已经得到了回答,但是我可以给您留下一些我在面对此BOM问题时发现的其他资源

使用此页面,您可以检查特定文件是否包含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中有一个选项,
zend.multibyte
,它允许php读取带有BOM的文件,而无需给出已发送的
标题
错误

从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

在PHP中,除了“headers ready sent”错误外,BOM表的存在还可能以更微妙的方式破坏浏览器中的HTML

请参见此以了解问题的概要


出现这种情况时,不仅呈现页面顶部通常有明显的空白,而且如果您在Firefox或Chrome中检查HTML,您可能会注意到头部部分是空的,其元素似乎在主体中。当然,查看源代码会显示所有应该显示的内容,但不知何故浏览器对其的解释是错误的。

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

对于PHP文件,它不是文件,而是作为响应发送的生成的输出,因此显然,在开始时将所有PHP文件与BOM一起保存不是一个好主意,但这并不意味着您不应该在响应中使用BOM

实际上,您可以在doctype声明之前安全地插入以下代码(如果您正在生成HTML作为响应):


进一步阅读:

添加到@omabena answer使用此代码查找并从文件中删除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("."); 
函数fopen_utf8($filename){ $file=@fopen($filename,“r”); $bom=fread($file,3); 如果($bom!=b“\xEF\xBB\xBF”) { 返回false; } 其他的 { 返回true; } } 函数文件_数组($path,$exclude=“.|..| design”,$recursive=true){ $path=rtrim($path,“/”)“/”; $folder\u handle=opendir($path); $exclude_数组=分解(“|”,$exclude); $result=array(); 而(false!=($filename=readdir($folder\u handle)){ 如果(!in_数组(strtolower($filename),$exclude_数组)){ 如果(是_dir($path.$filename.“/”){ //需要包含完整的“路径”,否则它是一个无限循环 如果($recursive)$result[]=file_数组($path.$filename.“/”,$exclude,true); }否则{ if(fopen_utf8($path.$filename)) { //$result[]=$filename; echo($path.$filename.“
”); $pathname=$path.$filename;//将路径名更改为要删除BOM表的目标文件。 $file_handler=fopen($pathname,“r”); $contents=fread($file_handler,filesize($pathname)); fclose($file\u handler); 对于($i=0;$i<3;$i++){ $bytes[$i]=ord(substr($contents,$i,1)); } 如果($bytes[0]==0xef&&$bytes[1]==0xbb&&$bytes[2]==0xbf){ $file_handler=fopen($pathname,“w”); fwrite($file_handler,substr($contents,3)); fclose($file\u handler); printf(“%s BOM已删除。
n”,$pathname); } } } } } 返回$result; } $files=文件数组(“.”);
谢谢您的建议。我明白我的立场,我想我会做一个体面的选择,拼写我的nam,而不是编码检测启发式,这是一种奇怪的妥协