1.新加通过curl的参数就知道是不是有bom在http头
2.对svn里加入 钩子来去掉里面的bom头。
3.对shell怎么去掉bom进行了摘录。 2013-08-14
一同事在输出XML的时候在firefox下没有问题,在IE下提示:
文档的顶层无效。处理资源 'http://public.sina.com.cn/message/program/application/1.php?uid=1&group=0&status=2&charset=utf-8&datatype=xm...
<?xml version="1.0" encoding="UTF-8"?>
^
蒙了,我找了整个她的哪个输出的php程序,都没有发现问题,但是在我将源代码保存后,通过editplus查看的时候,发现前面有一个不明飞行物,于是经过一步一步的调试发现原来在底层的数据层有一个utf8编码的bom,通过editplus看不出来,通过zend for eclipse6.1.*也看不出来,但是可以通过vi zend studio看到这个玩意!
vi 看到: <feff>
zend studio:看到一个小点。。。
zend studio 通过gbk编码:出现: 锘�
这种问题可以通过:notepad++ 的转换功能给转换为没有bom即可,完毕!
再次追溯原因:
通过svn查到,其出现这个原因是由于以下步骤操作导致的:
1.用记事本建立一个ansi的文本文件为phptest.php ,写入<?php ?>用zend studio打开没有发现问题。
2.然后通过记事本打开,另存为utf-8.用zend studio打开发现问题,<?php 前面出现 锘� (GBK编码打开是这样,设为uft-8后出现一个小点。。。)。
总结:
最后,我用记事本建立ansi文件,然后写入<?php ?>,再用editplus打开,然后通过另存为utf8,没有发现改问题,看来确实是记事本的问题!
最好用editplus建立utf8文件,谢谢!
如有bom输出会在setcookie的时候出现下面错误:Cannot modify header information - headers already sent by ....
如果在setcookie之前输出了任何文本内容,便会有上述错误提示。由于页面头部require了若干文件,一行行排查是很麻烦的事情!
解决方法如下:
我在该页面顶部加上:
在setcookie之前加上代码:
这是为了获取setcookie之前页面输出的内容。页面运行后,显示输出了一个空字符串,也就是说,setcookie之前没有任何输出。
避免方法:用vim打开了源文件,发觉vim有打开bomb选项,怀疑因此给代码添加了隐藏的字符串,关闭之: set nobomb
http://hi.baidu.com/jimmyhouse/blog/item/247dd517bb77040fc83d6d2f.html
http://www.phpq.net/research/php-utf8-bom.html
http://www.phpchina.com/html/80/t-37580.html
工作心得
对于上次邮件里面讨论到的PHP BOM问题,我来说来句就当心得吧,其实这个BOM问题一直在我们进行开发的时候经常出现,前些日子在企业邮箱里面第一次遇到这个问题,当时好像是企业的图标LOGO没有办法显示出来,因为<img src="img.php">,是img.php去读一个图片的内容然后给img显示,经过长仔细排查出现在输出图片资源前就有输出,那时候用的是notepad+editplus,最后用Zend studio来看这个文件头出现一个锘�字,证明了该问题。
第二次遇到BOM问题,是陈鑫鑫在纸条项目里面输出XML数据到IE浏览器中展现出现XML错误。
第三次也就是我们的记录APP调用外部接口返回用户的昵称出现乱码,经琳琳查也由BOM造成!
为何经常出现这种类似的问题,我看大家都在按照自己的方式来建立和开发PHP,特别是用Notepad来新建文件,系统默认在是ANSI格式,但我们的PHP编码是UTF-8的,于是又通过Notepad的另存为修改为UTF-8格式的,这样也就产生了一个BOM,最后,再用现在统一的开发工具Zend for eclipse去编辑这个带BOM的PHP文件,但BOM依然存在文件当中,它一般是表现不出任何问题,但一旦在页面前不能有输出的情况:如上面我遇到的三种情况它也就显现出来了。
BOM如此讨厌,该如何避免:
建议:
1. 切实统一开发工具:统一用Zend for eclipse 来新建PHP文件,和修改PHP文件编码!
2. 在项目完成后对目录里面所有的PHP 文件进行遍历驱出有可能出现的BOM。如:用sed批量替换掉bom:(syscore目录和所有下级目录的PHP文件替换)
补充:
bluexchen(陈胜益) 17:44:39
一:
用Shell如何清除一个目录下所有带BOM的文件中的BOM信息:
在Linux下的SVN中的文件,可能由于开发人员的编辑器的问题,上传上来后的文件带有utf8的BOM,会造成页面访问的问题,现在需要一个shell命令,一键清除一个目录下所有带BOM的文件中的BOM信息。
grep -r -I -l $'^\xEF\xBB\xBF' /path | xargs sed -i 's/^\xEF\xBB\xBF//g'
来自:http://www.dewen.org/q/4111
二:
使用Shell去除BOM:
发现有些文档在Shell下面处理的时候,第一个字节总是无法正常显示,出现乱码. 后来发现原来是BOM在作怪,BOM一共占用了3个字节. 通过UE可以在保存的时候,选择不保存BOM来去除.
但是我既然是在Linux下面做处理,为什么不直接通过Shell脚本来处理呢.查了资料之后发现下面的命令可以实现.
echo -ne '\xef\xbb\xbf123456' | awk '{if(NR==1)sub(/^\xef\xbb\xbf/,""); print}'
-ne是确保可以打印出16进制
\xef\xbb\xbf是UTF8 BOM的16进制表示
awk 后面命令意思就是,如果第一行是以UTF8 的BOM开头,则去除
BOM的详细解释
http://www.cnblogs.com/chengmo/archive/2010/10/30/1864004.html
来自:http://flyfoxs.iteye.com/blog/1485713
shell> curl -s http://phone.10086.cn/ | head -1 | sed -n l
\357\273\277<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional\
//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r$
如上所示,前三个字节分别是357、273、277,这就是八进制的BOM。
curl -s http://phone.10086.cn/ | head -1 | hexdump -C
00000000 ef bb bf 3c 21 44 4f 43 54 59 50 45 20 68 74 6d |...<!DOCTYPE htm|
00000010 6c 20 50 55 42 4c 49 43 20 22 2d 2f 2f 57 33 43 |l PUBLIC "-//W3C|
00000020 2f 2f 44 54 44 20 58 48 54 4d 4c 20 31 2e 30 20 |//DTD XHTML 1.0 |
00000030 54 72 61 6e 73 69 74 69 6f 6e 61 6c 2f 2f 45 4e |Transitional//EN|
00000040 22 20 22 68 74 74 70 3a 2f 2f 77 77 77 2e 77 33 |" "http://www.w3|
00000050 2e 6f 72 67 2f 54 52 2f 78 68 74 6d 6c 31 2f 44 |.org/TR/xhtml1/D|
00000060 54 44 2f 78 68 74 6d 6c 31 2d 74 72 61 6e 73 69 |TD/xhtml1-transi|
00000070 74 69 6f 6e 61 6c 2e 64 74 64 22 3e 0d 0a |tional.dtd">..|
如上所示,前三个字节分别是EF、BB、BF,这就是十六进制的BOM。
注:用到了第三方网站的页面,不能保证例子始终可用。 实际做项目开发时,可能会面对成百上千个文本文件,如果有几个文件混入了BOM,那么很难察觉,如果没有带BOM的UTF-8文本文件,可以用vi杜撰几个,相关命令如下:
设置UTF-8编码:
:set fileencoding=utf-8
添加BOM:
:set bomb
删除BOM:
:set nobomb
查询BOM:
:set bomb?
如何检测UTF-8编码中的BOM呢?
shell> grep -r -I -l $'^\xEF\xBB\xBF' /path
如何删除UTF-8编码中的BOM呢?
shell> grep -r -I -l $'^\xEF\xBB\xBF' /path | xargs sed -i 's/^\xEF\xBB\xBF//;q'
推荐:如果你使用SVN的话,可以在pre-commit钩子里加上相关代码用以杜绝BOM。
#!/bin/bash
REPOS="$1"
TXN="$2"
SVNLOOK=/usr/bin/svnlook
for FILE in $($SVNLOOK changed -t "$TXN" "$REPOS" | awk '/^[AU]/ {print $NF}'); do
if $SVNLOOK cat -t "$TXN" "$REPOS" "$FILE" | grep -q $'^\xEF\xBB\xBF'; then
echo "Byte Order Mark be found in $FILE" 1>&2
exit 1
fi
done
来自:http://huoding.com/2011/05/14/78
2.对svn里加入 钩子来去掉里面的bom头。
3.对shell怎么去掉bom进行了摘录。 2013-08-14
一同事在输出XML的时候在firefox下没有问题,在IE下提示:
文档的顶层无效。处理资源 'http://public.sina.com.cn/message/program/application/1.php?uid=1&group=0&status=2&charset=utf-8&datatype=xm...
<?xml version="1.0" encoding="UTF-8"?>
^
蒙了,我找了整个她的哪个输出的php程序,都没有发现问题,但是在我将源代码保存后,通过editplus查看的时候,发现前面有一个不明飞行物,于是经过一步一步的调试发现原来在底层的数据层有一个utf8编码的bom,通过editplus看不出来,通过zend for eclipse6.1.*也看不出来,但是可以通过vi zend studio看到这个玩意!
vi 看到: <feff>
zend studio:看到一个小点。。。
zend studio 通过gbk编码:出现: 锘�
这种问题可以通过:notepad++ 的转换功能给转换为没有bom即可,完毕!
再次追溯原因:
通过svn查到,其出现这个原因是由于以下步骤操作导致的:
1.用记事本建立一个ansi的文本文件为phptest.php ,写入<?php ?>用zend studio打开没有发现问题。
2.然后通过记事本打开,另存为utf-8.用zend studio打开发现问题,<?php 前面出现 锘� (GBK编码打开是这样,设为uft-8后出现一个小点。。。)。
总结:
最后,我用记事本建立ansi文件,然后写入<?php ?>,再用editplus打开,然后通过另存为utf8,没有发现改问题,看来确实是记事本的问题!
最好用editplus建立utf8文件,谢谢!
如有bom输出会在setcookie的时候出现下面错误:Cannot modify header information - headers already sent by ....
如果在setcookie之前输出了任何文本内容,便会有上述错误提示。由于页面头部require了若干文件,一行行排查是很麻烦的事情!
解决方法如下:
我在该页面顶部加上:
ob_start();
在setcookie之前加上代码:
ob_get_clean();
这是为了获取setcookie之前页面输出的内容。页面运行后,显示输出了一个空字符串,也就是说,setcookie之前没有任何输出。
避免方法:用vim打开了源文件,发觉vim有打开bomb选项,怀疑因此给代码添加了隐藏的字符串,关闭之: set nobomb
http://hi.baidu.com/jimmyhouse/blog/item/247dd517bb77040fc83d6d2f.html
http://www.phpq.net/research/php-utf8-bom.html
http://www.phpchina.com/html/80/t-37580.html
工作心得
对于上次邮件里面讨论到的PHP BOM问题,我来说来句就当心得吧,其实这个BOM问题一直在我们进行开发的时候经常出现,前些日子在企业邮箱里面第一次遇到这个问题,当时好像是企业的图标LOGO没有办法显示出来,因为<img src="img.php">,是img.php去读一个图片的内容然后给img显示,经过长仔细排查出现在输出图片资源前就有输出,那时候用的是notepad+editplus,最后用Zend studio来看这个文件头出现一个锘�字,证明了该问题。
第二次遇到BOM问题,是陈鑫鑫在纸条项目里面输出XML数据到IE浏览器中展现出现XML错误。
第三次也就是我们的记录APP调用外部接口返回用户的昵称出现乱码,经琳琳查也由BOM造成!
为何经常出现这种类似的问题,我看大家都在按照自己的方式来建立和开发PHP,特别是用Notepad来新建文件,系统默认在是ANSI格式,但我们的PHP编码是UTF-8的,于是又通过Notepad的另存为修改为UTF-8格式的,这样也就产生了一个BOM,最后,再用现在统一的开发工具Zend for eclipse去编辑这个带BOM的PHP文件,但BOM依然存在文件当中,它一般是表现不出任何问题,但一旦在页面前不能有输出的情况:如上面我遇到的三种情况它也就显现出来了。
BOM如此讨厌,该如何避免:
建议:
1. 切实统一开发工具:统一用Zend for eclipse 来新建PHP文件,和修改PHP文件编码!
2. 在项目完成后对目录里面所有的PHP 文件进行遍历驱出有可能出现的BOM。如:用sed批量替换掉bom:(syscore目录和所有下级目录的PHP文件替换)
find ./syscore -type f -name "*.php" -exec sed -i '1s/^\xef\xbb\xbf//' {} \;
<?
//此文件用于快速测试UTF8编码的文件是不是加了BOM,并可自动移除
//By Bob Shen
$basedir="./paper/tech/trunk/message"; //修改此行为需要检测的目录,点表示当前目录
$auto=0; //是否自动移除发现的BOM信息。1为是,0为否。
//以下不用改动
if ($dh = opendir($basedir)) {
while (($file = readdir($dh)) !== false) {
if ($file!='.' && $file!='..' && !is_dir($basedir."/".$file)) echo "filename: $file ".checkBOM("$basedir/$file")." <br>";
}
closedir($dh);
}
function checkBOM ($filename) {
global $auto;
$contents=file_get_contents($filename);
$charset[1]=substr($contents, 0, 1);
$charset[2]=substr($contents, 1, 1);
$charset[3]=substr($contents, 2, 1);
if (ord($charset[1])==239 && ord($charset[2])==187 && ord($charset[3])==191) {
if ($auto==1) {
$rest=substr($contents, 3);
rewrite ($filename, $rest);
return ("<font color=red>BOM found, automatically removed.</font>");
} else {
return ("<font color=red>包含BOM</font>");
}
}
else return ("未发现BOM");
}
function rewrite ($filename, $data) {
$filenum=fopen($filename,"w");
flock($filenum,LOCK_EX);
fwrite($filenum,$data);
fclose($filenum);
}
?>
//此文件用于快速测试UTF8编码的文件是不是加了BOM,并可自动移除
//By Bob Shen
$basedir="./paper/tech/trunk/message"; //修改此行为需要检测的目录,点表示当前目录
$auto=0; //是否自动移除发现的BOM信息。1为是,0为否。
//以下不用改动
if ($dh = opendir($basedir)) {
while (($file = readdir($dh)) !== false) {
if ($file!='.' && $file!='..' && !is_dir($basedir."/".$file)) echo "filename: $file ".checkBOM("$basedir/$file")." <br>";
}
closedir($dh);
}
function checkBOM ($filename) {
global $auto;
$contents=file_get_contents($filename);
$charset[1]=substr($contents, 0, 1);
$charset[2]=substr($contents, 1, 1);
$charset[3]=substr($contents, 2, 1);
if (ord($charset[1])==239 && ord($charset[2])==187 && ord($charset[3])==191) {
if ($auto==1) {
$rest=substr($contents, 3);
rewrite ($filename, $rest);
return ("<font color=red>BOM found, automatically removed.</font>");
} else {
return ("<font color=red>包含BOM</font>");
}
}
else return ("未发现BOM");
}
function rewrite ($filename, $data) {
$filenum=fopen($filename,"w");
flock($filenum,LOCK_EX);
fwrite($filenum,$data);
fclose($filenum);
}
?>
<?php
/*
查找一个目录里面的UTF-8 Born 头
用法
/opt/bin/php GetUtf8Born.php {dir}
例如
/opt/bin/php GetUtf8Born.php /opt/www/
*/
$is_fix_file = 1; //定义是否修复文件 1 为不修复 2 为修复
$d = $_SERVER['argv'][1];
if (!is_dir($d)) exit("Not Dir\n");
$shell = "/usr/bin/find $d -type f";
$r = exec($shell, $s_r);
if(!empty($s_r))
{
foreach($s_r as $file)
{
if(GetBorn($file))
{
echo $file . "\n";
if($is_fix_file == 2)
{
FixBorn($file);
}
}
}
}
exit;
function FixBorn($file)
{
if(!is_file($file))
{
return false;
}
$file_base_name = basename($file);
$file_path = dirname($file);
$r = ReadF($file, $file_string);
if(!$r)
{
return false;
}
//Utf-8 头占用3个字符占位 去掉即可
$new_string = substr($file_string, 3);
//开始备份文件
if (!copy($file, $file_path . "/Utf8Bom_" . $file_base_name))
{
return false;
}
// 写入新文件
if(!WriteF($file, $new_string))
{
return false;
}
return true;
}
function ReadF($file, &$string)
{
$fp = fopen($file, "r");
if(!$fp)
{
return false;
}
while (!feof ($fp))
{
$string .= fgets($fp, 1024);
}
fclose($fp);
return true;
}
function WriteF($file, $string)
{
$fp = fopen($file, "w+");
if(!$fp || !is_writable($file))
{
return false;
}
if (!fwrite($fp, $string))
{
return false;
}
fclose($fp);
return true;
}
function GetBorn($file)
{
if(!is_file($file))
{
return false;
}
$fp = fopen($file, "r");
$s = fgets($fp, 64);
fclose($fp);
$s = trim(bin2hex($s));
//if (strpos($s, "efbbbf") !== false)
if (substr($s, 0, 6) == "efbbbf")
{
return true;
}
return false;
}
?>
/*
查找一个目录里面的UTF-8 Born 头
用法
/opt/bin/php GetUtf8Born.php {dir}
例如
/opt/bin/php GetUtf8Born.php /opt/www/
*/
$is_fix_file = 1; //定义是否修复文件 1 为不修复 2 为修复
$d = $_SERVER['argv'][1];
if (!is_dir($d)) exit("Not Dir\n");
$shell = "/usr/bin/find $d -type f";
$r = exec($shell, $s_r);
if(!empty($s_r))
{
foreach($s_r as $file)
{
if(GetBorn($file))
{
echo $file . "\n";
if($is_fix_file == 2)
{
FixBorn($file);
}
}
}
}
exit;
function FixBorn($file)
{
if(!is_file($file))
{
return false;
}
$file_base_name = basename($file);
$file_path = dirname($file);
$r = ReadF($file, $file_string);
if(!$r)
{
return false;
}
//Utf-8 头占用3个字符占位 去掉即可
$new_string = substr($file_string, 3);
//开始备份文件
if (!copy($file, $file_path . "/Utf8Bom_" . $file_base_name))
{
return false;
}
// 写入新文件
if(!WriteF($file, $new_string))
{
return false;
}
return true;
}
function ReadF($file, &$string)
{
$fp = fopen($file, "r");
if(!$fp)
{
return false;
}
while (!feof ($fp))
{
$string .= fgets($fp, 1024);
}
fclose($fp);
return true;
}
function WriteF($file, $string)
{
$fp = fopen($file, "w+");
if(!$fp || !is_writable($file))
{
return false;
}
if (!fwrite($fp, $string))
{
return false;
}
fclose($fp);
return true;
}
function GetBorn($file)
{
if(!is_file($file))
{
return false;
}
$fp = fopen($file, "r");
$s = fgets($fp, 64);
fclose($fp);
$s = trim(bin2hex($s));
//if (strpos($s, "efbbbf") !== false)
if (substr($s, 0, 6) == "efbbbf")
{
return true;
}
return false;
}
?>
补充:
bluexchen(陈胜益) 17:44:39
<?php
$aa = headers_sent();
var_dump($aa);
session_start();
if (isset($_SESSION['test_sess'])){
$_SESSION['test_sess']++;
}else{
$_SESSION['test_sess'] = 0;
}
echo $_SESSION['test_sess'];
?>;
$aa = headers_sent();
var_dump($aa);
session_start();
if (isset($_SESSION['test_sess'])){
$_SESSION['test_sess']++;
}else{
$_SESSION['test_sess'] = 0;
}
echo $_SESSION['test_sess'];
?>;
一:
用Shell如何清除一个目录下所有带BOM的文件中的BOM信息:
在Linux下的SVN中的文件,可能由于开发人员的编辑器的问题,上传上来后的文件带有utf8的BOM,会造成页面访问的问题,现在需要一个shell命令,一键清除一个目录下所有带BOM的文件中的BOM信息。
grep -r -I -l $'^\xEF\xBB\xBF' /path | xargs sed -i 's/^\xEF\xBB\xBF//g'
来自:http://www.dewen.org/q/4111
二:
使用Shell去除BOM:
发现有些文档在Shell下面处理的时候,第一个字节总是无法正常显示,出现乱码. 后来发现原来是BOM在作怪,BOM一共占用了3个字节. 通过UE可以在保存的时候,选择不保存BOM来去除.
但是我既然是在Linux下面做处理,为什么不直接通过Shell脚本来处理呢.查了资料之后发现下面的命令可以实现.
echo -ne '\xef\xbb\xbf123456' | awk '{if(NR==1)sub(/^\xef\xbb\xbf/,""); print}'
-ne是确保可以打印出16进制
\xef\xbb\xbf是UTF8 BOM的16进制表示
awk 后面命令意思就是,如果第一行是以UTF8 的BOM开头,则去除
BOM的详细解释
http://www.cnblogs.com/chengmo/archive/2010/10/30/1864004.html
来自:http://flyfoxs.iteye.com/blog/1485713
shell> curl -s http://phone.10086.cn/ | head -1 | sed -n l
\357\273\277<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional\
//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r$
如上所示,前三个字节分别是357、273、277,这就是八进制的BOM。
curl -s http://phone.10086.cn/ | head -1 | hexdump -C
00000000 ef bb bf 3c 21 44 4f 43 54 59 50 45 20 68 74 6d |...<!DOCTYPE htm|
00000010 6c 20 50 55 42 4c 49 43 20 22 2d 2f 2f 57 33 43 |l PUBLIC "-//W3C|
00000020 2f 2f 44 54 44 20 58 48 54 4d 4c 20 31 2e 30 20 |//DTD XHTML 1.0 |
00000030 54 72 61 6e 73 69 74 69 6f 6e 61 6c 2f 2f 45 4e |Transitional//EN|
00000040 22 20 22 68 74 74 70 3a 2f 2f 77 77 77 2e 77 33 |" "http://www.w3|
00000050 2e 6f 72 67 2f 54 52 2f 78 68 74 6d 6c 31 2f 44 |.org/TR/xhtml1/D|
00000060 54 44 2f 78 68 74 6d 6c 31 2d 74 72 61 6e 73 69 |TD/xhtml1-transi|
00000070 74 69 6f 6e 61 6c 2e 64 74 64 22 3e 0d 0a |tional.dtd">..|
如上所示,前三个字节分别是EF、BB、BF,这就是十六进制的BOM。
注:用到了第三方网站的页面,不能保证例子始终可用。 实际做项目开发时,可能会面对成百上千个文本文件,如果有几个文件混入了BOM,那么很难察觉,如果没有带BOM的UTF-8文本文件,可以用vi杜撰几个,相关命令如下:
设置UTF-8编码:
:set fileencoding=utf-8
添加BOM:
:set bomb
删除BOM:
:set nobomb
查询BOM:
:set bomb?
如何检测UTF-8编码中的BOM呢?
shell> grep -r -I -l $'^\xEF\xBB\xBF' /path
如何删除UTF-8编码中的BOM呢?
shell> grep -r -I -l $'^\xEF\xBB\xBF' /path | xargs sed -i 's/^\xEF\xBB\xBF//;q'
推荐:如果你使用SVN的话,可以在pre-commit钩子里加上相关代码用以杜绝BOM。
#!/bin/bash
REPOS="$1"
TXN="$2"
SVNLOOK=/usr/bin/svnlook
for FILE in $($SVNLOOK changed -t "$TXN" "$REPOS" | awk '/^[AU]/ {print $NF}'); do
if $SVNLOOK cat -t "$TXN" "$REPOS" "$FILE" | grep -q $'^\xEF\xBB\xBF'; then
echo "Byte Order Mark be found in $FILE" 1>&2
exit 1
fi
done
来自:http://huoding.com/2011/05/14/78
作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/1333/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!
最后编辑: jackxiang 编辑于2013-8-14 13:55
评论列表