写PHP的朋友们肯定遇到过这样一个问题:通过header函数改变http协议头的时候,会出现一个类似下面格式的warning:
Warning: Cannot modify header information - headers already sent by
这是为什么呢?因为在使用header函数之前,
您不能输出任何东西,包括用echo或var_dump等输出函数的输出,还有在
<?php之前的空格。不过有的时候,我们并没有输出任何东西,却还是会出现这个错误,这是
因为我们的文件包含了BOM签名,我们必须把它去掉。下面我们就来讨论这个问题。
请看测试代码:
<?php
header("content-type:text/html;charset=utf-8");
die();
?>
这段代码就是简单的header一下,在<?php之前也没有任何输出,也没有空格,但是网页里还是提示了Cannot modify header information的警告信息。这说明,在<?php之前还有内容,只是编辑器没有显示出来。
我们用ultraEdit打开这个文件,切换到16进制,可以看到,在文本的开头,有EFBBBF,之后才是3C 3F 70 68 70 ( <?php ),说明,在<?php之前,确实存在着输出信息,因此,在修改header的时候,会得到警告信息。
这个EFBBBF是什么东西呢?它的名字叫BOM,Byte Order Mark,是在Windows下的一个约定,用于标记文本是否是Unicode。记事本程序就是通过这三个字节来判断文件是ANSI还是Unicode。
知道了问题发生的原因,下面,我们想办法把BOM去掉。用Dreamweaver打开这个php页面,然后进入页面设置(按Ctrl+J),弹出以下窗口:
取消选择“包括Unicode签名(BOM)”,确定就可以了。现在,我们再用UltraEdit打开看这个文件的16进制内容,如下图
可以看到,现在BOM信息已经没有了,文件直接以3C3F70开头了。
最后,我们刷新一下浏览器,发现现在已经没有Warning提示了,问题解决。
Ferris
2008-12-15
今天写JS的时候,遇到一个需求,我需要将一个文本文件的内容作为一个字符串赋值给一个变量,这个文本文件是多行的。首先,我想到了,将文本文件中的所有换行符替换成\n,将所有双引号替换成\",这样就可以将这个多行文本转换成单行文本了。不过,如果JS有类似于PHP的字符串定界符的话,就更好了。于是,在网上搜索了一下,找到了两个方法
我的文本文件内容:
Line1
Line2Line2
Line3
方法一(支持Firefox)
这个方法的原理是生成一个XML节点。因为XML可以使用CDATA来生成多行文本。然后,再将这个节点转换成字符串,就可以得到一个多行文本了。不过这个方法只在支持E4X的浏览器上有效。经过测试,Firefox3.0支持,IE7.0不支持。
代码如下:
var str = (<r><![CDATA[
Line1
Line2Line2
Line3
]]></r>).toString();
alert(str);
方法二(支持IE)
这个方法相当有创意,是网络上某个高人的杰作。
方法的原理是将多行文本写在一个函数体的多行注释内,然后,通过字符串解析函数,将多行文本分离出来,这样,整个文件内容也可以原封不动的复制到JS代码中。不过这个方法只在IE里支持,Firefox会将注释代码从函数体中移除。
Function.prototype.getMultiline = function()
{
var lines = new String(this);
lines = lines.substring(lines.indexOf("/*\r\n") + 4, lines.lastIndexOf("*/"));
return lines;
}
var str = function() {
/*
Line1
Line2Line2
Line3
*/
}.getMultiline();
alert(str);
Ferris
2008-12-10
千千静听网页版(FXPlayer 0.4 测试版)
版本信息 * 作者 - Ferris Xu
* 版本号 - 0.4 测试版
* 更新时间 - 2008年02月01日
* 兼容的浏览器:IE,Firefox 2.x
特点 * 纯Javascript的实现,无需任何第3方的JS框架)
* 面向对象的架构设计,自定义播放器事件
* 自定义UI组件,可拖动,缩放窗口
* 兼容IE和Firefox2.x
* 提供了音量,进度等控制,界面和千千静听完全一致
* 兼容千千静听5.0的播放列表,基本兼容千千静听的皮肤,能在播放时切换皮肤
* 播放时动态歌词的显示
说明 *
本程序仅用于演示,以及Javascript技术的学习和交流,不会进行任何商业行为。 * 由于时间的关系,本程序在播放列表功能上没有全部完成。
* 由于千千静听的皮肤是一个压缩包,并且里面的图片都是BMP的,在网页上无法使用,所以本程序所兼容的是已经解压缩的,并且将所有图片都转换成网页格式的图片(如gif)。
* 由于Firefox3在WMP插件的事件捕捉上存在Bug,因此本程序不能在Firefox3上面正确运行
*
处于对千千静听的喜爱,我开发了它的JS版本,并取名为千千静听网页版。若有不妥,请告知,谢谢。效果截图演示地址http://www.CoffeeCat.net.cn/web/fxplayer程序下载http://www.cnitblog.com/Files/CoffeeCat/fxplayer0.4.rar
最近在写一个JS程序,遇到这样一个问题,请看代码:
var myobject = {};
myobject.delete = function()
{
alert ("call delete");
};
myobject.delete();
这段代码从思想上没有任何问题,定义1个对象myobject,并且给它一个删除的方法名为delete,最后调用delete方法。这段代码在Firefox下能正常运行,但在IE下却报语法错误。原因相信大家也发现了,IE把delete看成是关键字了,而Firefox会把delete看成是myobject对象里的一个方法。所以,把delete方法改名字就对了,以后尽量不要用JS关键字做方法名,如new,delete等
因此,如果您在写JS程序时,遇到Firefox正常,但IE报语法错误,通常情况下,都是您使用了delete或者new关键字定义了方法名,您可以从这方面下手debug。
最后聊点题外话,介绍一下JS在Firefox以及IE下的调试工具。Firefox下就不说了,有大名鼎鼎的
Firebug,这款工具不仅查看DOM结构,JS错误信息等,最重要的它能够监视网络的数据。IE下的调试工具也不少,微软的IE Developer Toolbar和Firebug挺类似的,只是它没有监视网络数据的功能,这对调试Ajax代码比较不好。调试JS的工具我觉得最好的是Companion JS,我觉得它是IE下最好的JS调试工具,它能够准确定位到出错的JS代码,而且它是免费的。如果没有Companion,我可能需要更多的时间才能找到罪魁祸首delete的。另外,Firebug也有IE版的,不过IE版的Firebug是完全用JS写的,处理速度十分缓慢,特别是分析DOM树、分析CSS等,速度奇慢,缺少实用性,而且Firebug for IE不能检测网络数据。
Ferris
2008-09-02
Smarty的注释方式是将注释内容写在成对的星号中,如
{* 这里是注释文本 *}
当然,也可以这样
{*
这里是第1行注释文本
这里是第2行注释文本
*}
在Smarty手册里将第2种方法称为Multiline smarty comment(多行注释)。这种一般用于说明Smarty程序的含义,而不是起到隐藏客户端代码的功能。
下面要讨论一种特殊的多行注释的方法,请先看下面的例子
<div>
{ if $con == false }
一些HTML代码或者是含有Javascript的代码
{ /if }
</div>
这是一段HTML代码,其中使用了Smarty进行了逻辑控制。但是,现在我们暂时不想让客户端显示这段代码,那么最好的方法就是将整个div注释掉。您可能会想到
{ * }
<div>
{ if $con == false }
一些HTML代码或者是含有Javascript的代码
{ /if }
</div>
{ * }
可惜,这样做是无效的。因此,Smarty所说的多行注释其实是在不打断Smarty程序分隔符的情况下的多行注释。那我们如何进行这样的注释呢?其实,我们可以巧妙得使用if语句来进行注释,如下:
{ if 0==1 }
<div>
{ if $con == false }
一些HTML代码或者是含有Javascript的代码
{ /if }
</div>
{ /if }
if 0 == 1 这个条件是永远不成立的,因此,中间的代码也就运行不了了,这样就间接起到了一个注释的作用了。当然,为了提高程序的可读性,您可以在if旁边添加一个单行注释,来说明这个if语句的作用是注释。
Ferris
2008-08-14
摘要: 首先,要和大家说声抱歉,因为我有半年没有更新博客了。这半年过得很充实,也很忙碌,以至于没有时间写博客了。今天要探讨的是PHP网页导出Word文档的方法,使用其他语言的朋友也可以参考,因为原理是差不多的。
原理
一般,有2种方法可以导出doc文档,一种是使用com,并且作为php的一个扩展库安装到服务器上,然后创建一个com,调用它的方法。安装过office...
阅读全文
Javascript本身并不支持面向对象,它没有访问控制符,它没有定义类的关键字class,它没有支持继承的extend或冒号,它也没有用来支持虚函数的virtual,不过,Javascript是一门灵活的语言,下面我们就看看没有关键字class的Javascript如何实现类定义,并创建对象。
一:定义类并创建类的实例对象在Javascript中,我们用function来定义类,如下:
function Shape()
{
var x=1;
var y=2;
}
你或许会说,疑?这个不是定义函数吗?没错,这个是定义函数,我们定义了一个Shape函数,并对x和y进行了初始化。不过,如果你换个角度来看,这个就是定义一个Shape类,里面有两个属性x和y,初始值分别是1和2,只不过,我们定义类的关键字是function而不是class。
然后,我们可以创建Shape类的对象aShape,如下:
var aShape = new Shape();
二:定义公有属性和私有属性我们已经创建了aShape对象,但是,当我们试着访问它的属性时,会出错,如下:
aShape.x=1;
这说明,用var定义的属性是私有的。我们需要使用this关键字来定义公有的属性
function Shape()
{
this.x=1;
this.y=2;
}
这样,我们就可以访问Shape的属性了,如。
aShape.x=2;
好,我们可以根据上面的代码总结得到:用var可以定义类的private属性,而用this能定义类的public属性。
三:定义公有方法和私有方法在Javascript中,函数是Function类的实例,Function间接继承自Object,所以,函数也是一个对象,因此,我们可以用赋值的方法创建函数,当然,我们也可以将一个函数赋给类的一个属性变量,那么,这个属性变量就可以称为方法,因为它是一个可以执行的函数。代码如下:
function Shape()
{
var x=0;
var y=1;
this.draw=function()
{
//print;
};
}
我们在上面的代码中定义了一个draw,并把一个function赋给它,下面,我们就可以通过aShape调用这个函数,OOP中称为公有方法,如:
aShape.draw();
如果用var定义,那么这个draw就变成私有的了,OOP中称为私有方法,如
function Shape()
{
var x=0;
var y=1;
var draw=function()
{
//print;
};
}
这样就不能使用aShape.draw调用这个函数了。
三:构造函数Javascript并不支持OOP,当然也就没有构造函数了,不过,我们可以自己模拟一个构造函数,让对象被创建时自动调用,代码如下:
function Shape()
{
var init = function()
{
//构造函数代码
};
init();
}
在Shape的最后,我们人为的调用了init函数,那么,在创建了一个Shape对象是,init总会被自动调用,可以模拟我们的构造函数了。
四:带参数的构造函数如何让构造函数带参数呢?其实很简单,将要传入的参数写入函数的参数列表中即可,如
function Shape(ax,ay)
{
var x=0;
var y=0;
var init = function()
{
//构造函数
x=ax;
y=ay;
};
init();
}
这样,我们就可以这样创建对象:
var aShape = new Shape(0,1);
五:静态属性和静态方法在Javascript中如何定义静态的属性和方法呢?如下所示
function Shape(ax,ay)
{
var x=0;
var y=0;
var init = function()
{
//构造函数
x=ax;
y=ay;
};
init();
}
Shape.count=0;//定义一个静态属性count,这个属性是属于类的,不是属于对象的。
Shape.staticMethod=function(){};//定义一个静态的方法
有了静态属性和方法,我们就可以用类名来访问它了,如下
alert ( Shape.count );
Shape.staticMethod();
注意:静态属性和方法都是公有的,目前为止,我不知道如何让静态属性和方法变成私有的~
六:在方法中访问本类的公有属性和私有属性在类的方法中访问自己的属性,Javascript对于公有属性和私有属性的访问方法有所不同,请大家看下面的代码
function Shape(ax,ay)
{
var x=0;
var y=0;
this.gx=0;
this.gy=0;
var init = function()
{
x=ax;//访问私有属性,直接写变量名即可
y=ay;
this.gx=ax;//访问公有属性,需要在变量名前加上this.
this.gy=ay;
};
init();
}
七:this的注意事项根据笔者的经验,类中的this并不是一直指向我们的这个对象本身的,主要原因还是因为Javascript并不是OOP语言,而且,函数和类均用function定义,当然会引起一些小问题。
this指针指错的场合一般在事件处理上面,我们想让某个对象的成员函数来响应某个事件,当事件被触发以后,系统会调用我们这个成员函数,但是,传入的this指针已经不是我们本身的对象了,当然,这时再在成员函数中调用this当然会出错了。
应网友moon的建议,加上this指错的例子
function Shape()
{
var x=123;
var init = function()
{
alert ( this.x ); //此处会输出undefined,而不是123,原因:此处的this属于init这个function内部,而init这个function中并没有定义x这个变量
};
init();
}
var shape = new Shape();
解决方法是我们在定义类的一开始就将this保存到一个私有的属性中,以后,我们可以用这个属性代替this。我用这个方法使用this指针相当安全,而且很是省心~
我们修改一下代码,解决this问题。对照第六部分的代码看,你一定就明白了
function Shape(ax,ay)
{
var _this=this; //把this保存下来,以后用_this代替this,这样就不会被this弄晕了
var x=0;
var y=0;
_this.gx=0;
_this.gy=0;
var init = function()
{
x=ax;//访问私有属性,直接写变量名即可
y=ay;
_this.gx=ax;//访问公有属性,需要在变量名前加上this.
_this.gy=ay;
};
init();
}
以上我们聊了如何在Javascript中定义类,创建类的对象,创建公有和私有的属性和方法,创建静态属性和方法,模拟构造函数,并且讨论了容易出错的this。
关于Javascript中的OOP实现就聊到这里,以上是最实用的内容,一般用Javascript定义类,创建对象用以上的代码已经足够了。当然,你还可以用mootools或prototype来定义类,创建对象。我用过mootools框架,感觉很不错,它对Javascript的类模拟就更完善了,还支持类的继承,有兴趣的读者可以去尝试一下。当然,如果使用了框架,那么在你的网页中就需要包含相关的js头文件,因此我还是希望读者能够在没有框架的情况下创建类,这样,代码效率较高,而且你也可以看到,要创建一个简单的类并不麻烦~
在下一个版本的Javascript中,将会加入对OOP的支持,届时,我们将看到class关键字,public、private访问控制符~extend继承。如果大家对下一代Javascript感兴趣,不妨可以先接触一下ActionScript3.0,这是一门相当先进的脚本语言,是Adobe收购Macromedia后的一个力作,它和Javascript一样,都属于ECMAScript,只不过AS3.0是ECMAScript的第4版的实现。要学习ActionScript3.0,我重点推荐孙颖老师的《ActionScript3殿堂之路》,这本书写的绝对好,特别是面向对象这部分,写的特别通俗易懂,例子生动,读完以后感觉很有收获,在赞叹新版的ECMAScript的同时,也给了我极大的动力继续深入学习OOP编程思想,有兴趣的读者不妨去品读一下~
Ferris
2008-2-25
最近在做web开发,其中有一个需求:利用Javascript获取要加载的图片的尺寸,所以很自然的,我就想到了img的onload方法,在firefox下开发完成后,我到IE下调试,发现img的onload事件很多情况下都不被调用。
我最初的代码如下:
var img = new Image;
img.src = "test.gif";
img.onload = function(){
alert ( img.width );
};
这段代码看着没什么问题,但是为什么onload没有被IE调用呢?因为IE会缓存图片,第2次加载的图片,不是从服务器上传过来的,而是从缓冲区里加载的。是不是从缓冲区里加载的图片就不触发onload事件呢?我于是我测试了以下代码,成功了~
var img = new Image;
img.onload = function(){
alert ( img.width );
};
img.src = "test.gif";
我把onload写到前面去,先告诉浏览器如何处理这张图片,再指定这张图片的源,这样就正常了。所以,不是IE没有触发onload事件,而是因为加载缓冲区的速度太快,以至于没有运行到img.onload的时候,onload事件已经触发了。这让我想到了Ajax,我们在写xmlhttp的时候,都是先指定onstatechange的回调函数,然后再send数据的,道理是一样的。
Ferris
2008-2-1
前阵子我一直在研究基于B/S架构的网络游戏开发(网页网络游戏),并写了一个Web版的盛大富翁客户端Demo。今天看到盛大网络出了一款基于B/S架构的网游:纵横天下,我感到很兴奋,同时,我也想谈一下个人的看法。
传统的网络游戏是C/S架构的,通俗点说,就是大家在玩游戏之前,先要安装游戏的客户端,然后才能进行游戏,也就是客户端(Client)/服务器(Server)模式。而B/S架构是什么意思呢?B就是Browser,浏览器,也就是说,大家只要打开浏览器,登陆到相关的网站,就可以玩的网游。
B/S架构的网络游戏,它最大的好处就是大家可以在任何联网的电脑上玩游戏,只要这台电脑上有浏览器。我曾经卸载过Vista,因为在Vista下不能玩盛大富翁。但如果盛大富翁变成B/S架构了,那我就算安装了Linux,我也可以放心的玩了。对于开发者而言,他们开发跨系统的网游代码会更加方便,因为几乎每个操作系统上都有浏览器,他们就不必去关心Linux下创建Socket的代码是怎么样的,他们也不必去考虑到底是用OpenGL还是DirectX。
当然,B/S架构的网游也有很多不成熟的地方,我下面列举几点
1:通讯方式有待改善
B/S游戏在通讯方面的能力,比C/S要弱很多,主要还是因为浏览器的通讯方式:我们发送一个URL给服务器,然后接收服务器返回的网页信息,连接就结束了,最后浏览器把网页信息显示出来。这样的通讯过程没有持久性可言,而网游的通讯最好是有持续性的,这样才可以有效降低服务器的负荷,提高带宽利用率,并使程序架构更合理,通讯更安全。
2:客户端技术功能有限
按照目前的技术,B/S架构的网游,一般只使用Javascript或Flash Action Script做客户端,Javascript尽管功能强大,但是运行效率能力很低,大家可以用一下Google的记事本,当你处理一篇比较长的文章时,你就会感到很恼火,因为很卡,CPU占用率一直是100%。另外,Javascript的绘图能力不好,不过用Javascript做交互性控件还是不错的选择。Flash的的计算能力也有限,但是Flash有很多比Javascript出色的地方,首先它可以全屏,然后,它的通讯方式要比Ajax好,最后,Flash的2D绘图能力相当出色。用Flash开发B/S架构的网游客户端是最好的选择,纵横天下也是这样做的。不过,我还是会先使用JS进行开发,因为我喜欢JS,而且JS的潜力无限,无需安装插件。我的盛大富翁网页版Demo也完全是用JS写的。个人猜想,以后的B/S架构的网游,可能是JS+Flash的整合,各取所长。
3:安全性问题
Javascript代码是完全公开的(虽然可以加密),Flash也有反编译工具,这样,客户端的代码就很容易被克隆,进而产生外挂程序,破坏游戏的公平性,并对服务器产生危害,不过这个问题目前只能通过增加验证机制,对游戏数据进行加密来解决。
我刚刚去体验了一下盛大的纵横天下,感觉做的还不错,是比较优秀的战略网游,不过不是很生动,还是以文字为主,没有很靓丽的视觉效果,上手不太容易。毕竟是第一款网页游戏,我相信今后会越做越好的。
纵横天下给了我不少动力,我会抓紧研究B/S架构的网络游戏,尽早推出我开发的网页游戏,给大家带来网络游戏的全新体验。
P.S:我下学期的毕业设计课题正好是“基于B/S架构的网络游戏开发”,能选到自己喜欢的课题真是开心。 ^_^
Ferris
2008-1-22
2007-1-28
注:今天我了解到Flash的Actionscript3.0提供了良好的,基于TCP/IP协议的socket支持,这样就可以为网页游戏提供良好的通讯支持,当然,就不会存在我上文中提到的无持久性的问题。而且,Flash可以和Javascript交互,看来,Flash将注定成为网页网络游戏技术
的主角。
今天帮同学解决了avi电影加载字幕的问题,简单记录一下,希望对大家有用~
方法:
1:先将idx和sub文件和avi文件放在一起
2:将idx和sub文件重命名,名字和avi的文件名一致
3:用Windows Media Player打开avi文件,点击播放菜单->字幕->开,就可以看到字幕显示出来了。
CoffeeCat
2008-1-1