寻虫记:BOM头制造的冤案,无故多出空白行
最近在做的一个网站发生了一个很诡异的BUG:
- 使用IE浏览页面时,一切都挺正常;
- 而使用Firefox浏览时,发现某些页面元素之间的距离比预期的要宽很多,HTML元素本身的hight、padding和margin值都很正常,只是元素之间像是增加了一个空行或一个类似于DIV的块级元素;用F12调出开发者工具查看后却没有发现任何多出的HTML元素或多余的代码;
- 再用Chrome进行查看,页面的显示效果和firefox一样,但是用F12查看后,发现确实是增加了多余的一行,表现为增加了一个空白字符串,但是占有一个整行的宽度。如下图中header元素的上下所示:
接下来排查错误:
一开始以为是CSS样式中的:before语句对页面元素有了影响,但是:before仅对body元素进行了设置,仅仅只是增加了一个元素,不会造成如此多的元素的间隔距离都拉开了的效果;且在删除:before语句后浏览,问题依然存在。因此排除了这个可能性。
然后开始仔细的检查(过程很痛苦),发现这些出问题的地方都有一个共同点:因为网站是采用静态化实现,使用了服务器端的静态包含,而每个多余的行都出现在每个包含文件(<!--#include virtual="**.inc" -->)的前面。于是去看包含文件的生成过程,去掉文件生成时头尾可能产生的换行符和空白串。但是更新程序后,重新生成静态文件,问题仍然存在。
后来实在找不到问题所在,只能先放一下去完成其他的功能。但是,这个没有解决的问题,一直萦绕在我的心头,时时都能想起它,时时都在想“为什么呢”?如鲠在喉,无法下咽。总觉得有什么事情没做完一样,做其他的事情时感觉也不踏实。
因为基本确认是包含文件出现了问题,于是集中在文件生成和包含这一块进行排除。在做其他事的时候无意中想到文件编码这一块的事情,于是就想会不会是这个因素的影响。于是上网搜索,发现了如下几篇文章:
1、什么是BOM头
3、XML的BOM
看完后,隐约觉得应该是找到问题所在了;于是看了看自己程序,发现在生成静态文件时,采用了UTF-8编码来设置字节流,同时在保存到文件时也采用了UTF-8编码,代码如下:
File.WriteAllText(Task.FullPath + filename + Task.Extension, content, Encoding.UTF8);
于是决定首先利用UE去除BOM头试试效果:打开某一个静态化后的inc文件,另存为时选择“UTF-8 无 BOM”,能BOM头。如下图:
保存文件后再进行浏览,问题不再出现。从而确定了BOM头在一些浏览器内解析时,会被解析为一个空行或者一个块级元素。在用程序保存文件时,如果指定了文件的编码格式为UTF-8,也会为文件增加BOM头。
因此生成文件时,改为去掉文件保存时指定的UTF-8编码,但字节流仍采用UTF-8编码处理。
content = Encoding.UTF8.GetString(bytes);
File.WriteAllText(Task.FullPath + filename + Task.Extension, content);
同时因为字节流采用UTF-8编码,在html页面里需要指定页面的编码方式,不然会出现乱码:
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
做完以上处理,再次重新生成所有inc文件后,在不同浏览器下刷新查看,发现问题均得到解决。
在确认了BUG的原因并最终解决了问题之后,居然找到了这样一篇文章:关于shtml页面include问题解决方案因为utf-8的BOM头引起的出现一个空行 !!为什么总是在费尽九牛二虎之力解决问题后,才发现这么一篇能精确指导解决问题的方案的文章呢?
另外,推荐一个关于编码方面的文章:由web程序出现乱码开始挖掘(Bom头、字符集与乱码)
做程序开发,确实是知道得越多,知道的就越少。坑太多啊。绝逼的学无止尽。
寻虫记:BOM头制造的冤案,无故多出空白行的更多相关文章
- 编码格式简介:ASCII码、ANSI、GBK、GB2312、GB18030和Unicode、UTF-8,BOM头
编码格式简介:ASCII码.ANSI.GBK.GB2312.GB18030和Unicode.UTF-8,BOM头 二进制: 只有0和1. 十进制.十六进制.八进制: 计算机其实挺笨的,它只认识0101 ...
- 什么是BOM头,BOM头有什么影响,怎么去掉BOM头
什么是bom头? 在utf-8编码文件中BOM在文件头部,占用三个字节,用来标示该文件属于utf-8编码,现在已经有很多软件识别bom头,但是还有些不能识别bom头,比如PHP就不能识别bom头,这也 ...
- 详解BOM头以及去掉BOM头的方法
类似WINDOWS自带的记事本等软件,在保存一个以UTF-8编码的文件时,会在文件开始的地方插入三个不可见的字符(0xEF 0xBB 0xBF,即BOM).它是一串隐藏的字符,用于让记事本等编辑器识别 ...
- PHP 版去bom头
原理: 找出文件前3个字符 如果它们对应的ASCII 值分别是 239,187,191 则判断为bom头,去掉前3个字符. 代码实现如下: $basedir = isset($_GET['dir'] ...
- 捉虫记(四)线程安全导致的HighCpu
一个朋友QQ群里说网站启动后会cpu很高,想要帮忙看一下dump. 1.打开windbg加载dump文件后第一个命令lmf,这个命令显示加载的dll以及路径,这样子可以找个dll来帮忙加载sos,(额 ...
- linux下bom头导致的php调用php接口 返回的json字符串 无法转成 数组,即json字符串无法解码的问题
今天很是郁闷,写了一个php接口,返回的是标准的json字符串,但是调用的php 就是无法json_decode(),返回错误码为4,最后终于找到原因,原来是蒙一个文件中有bom头,最后采用一个命令 ...
- 检测文件是否有BOM 头,并删除BOM头(php)
将下面文件放在网站根目录访问即可,它会遍历当前目录下所有子目录,检测文件是否含有BOM头,并删除BOM头 <?php //remove the utf-8 boms //by magicbug ...
- UTF-8 BOM头
BOM是什么 Unicode的学名是"Universal Multiple-Octet Coded Character Set",简称为UCS.UCS可以看作是"Unic ...
- linux下查找包含BOM头的文件和清除BOM头命令
查找包含BOM头的文件,命令如下: grep -r -I -l $'^\xEF\xBB\xBF' ./ 这条命令会查找当前目录及子目录下所有包含BOM头的文件,并把文件名在屏幕上输出. 但 ...
随机推荐
- 关联规则算法(The Apriori algorithm)详解
一.前言 在学习The Apriori algorithm算法时,参考了多篇博客和一篇论文,尽管这些都是很优秀的文章,但是并没有一篇文章详解了算法的整个流程,故整理多篇文章,并加入自己的一些注解,有了 ...
- [CareerCup] 7.7 The Number with Only Prime Factors 只有质数因子的数字
7.7 Design an algorithm to find the kth number such that the only prime factors are 3,5, and 7. 这道题跟 ...
- [CareerCup] 10.3 Integer not Contain in the File 文件中不包含的数
10.3 Given an input file with four billion non-negative integers, provide an algorithm to generate a ...
- 编写高质量iOS代码与OS X代码的effective 方法小结
一.熟悉OC: 了解OC的起源: OC和C++,Java等面向对象语言类似,不过有很方面差别.因为该语言使用 消息结构而非函数调用. 消息结构和函数调用的区别:前者是在其运行时所应执行的代码由运行环 ...
- IOS开发之——友盟社会化分享UMSocial_SDK的使用
友盟第三方官方网址:http://dev.umeng.com/social/ios/quick-integration
- 最长回文子串(Manacher算法)
回文字符串,想必大家不会不熟悉吧? 回文串会求的吧?暴力一遍O(n^2)很简单,但当字符长度很长时便会TLE,简单,hash+二分搞定,其复杂度约为O(nlogn), 而Manacher算法能够在线性 ...
- web性能优化之:no-cache与must-revalidate深入探究
引言 稍微了解HTTP协议的前端同学,相比对Cache-Control不会感到陌生,性能优化时经常都会跟它打交道. 常见的值有有private.public.no-store.no-cache.mus ...
- Visual Studio调试
一:C# CODING 技巧 1:TODO 然后 CTRL + W + T,打开任务列表,选中 Comments,就会显示所有待做的任务 2:打开所在的文件夹 右键单击任何一个文件选项卡, 选择&qu ...
- ThreadLocal类的实现用法
ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是threadlocalvariable(线程局部变量).也许把它命名为Thread ...
- c++ 中 delete p与 delete []p的区别
#include <cstdio> class A{private: int i;public: ~A() { printf("hi"); }};void d(A *) ...