CoffeeCat's IT Blog

解决PHP中的Cannot modify header information的问题

写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

posted @ 2008-12-15 12:48 CoffeeCat 阅读(1394) | 评论 (1)编辑 收藏

在Javascript中给变量赋多行字符串的方法

    今天写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

posted @ 2008-12-10 11:03 CoffeeCat 阅读(7599) | 评论 (0)编辑 收藏

我的千千静听网页版发布了

千千静听网页版(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

posted @ 2008-09-14 22:26 CoffeeCat 阅读(1574) | 评论 (0)编辑 收藏

一个在IE中报语法错误但在Firefox下却能正常运行的JS范例

最近在写一个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

posted @ 2008-09-02 15:26 CoffeeCat 阅读(2386) | 评论 (0)编辑 收藏

讨论Smarty中注释的方法

    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

posted @ 2008-08-14 13:10 CoffeeCat 阅读(3248) | 评论 (0)编辑 收藏

PHP网页导出Word文档的方法

     摘要: 首先,要和大家说声抱歉,因为我有半年没有更新博客了。这半年过得很充实,也很忙碌,以至于没有时间写博客了。今天要探讨的是PHP网页导出Word文档的方法,使用其他语言的朋友也可以参考,因为原理是差不多的。 原理     一般,有2种方法可以导出doc文档,一种是使用com,并且作为php的一个扩展库安装到服务器上,然后创建一个com,调用它的方法。安装过office...  阅读全文

posted @ 2008-08-07 18:25 CoffeeCat 阅读(20491) | 评论 (31)编辑 收藏

Javascript中的类实现

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

posted @ 2008-02-25 21:07 CoffeeCat 阅读(17056) | 评论 (25)编辑 收藏

解决IE中img.onload失效的方法

    最近在做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

posted @ 2008-02-01 13:46 CoffeeCat 阅读(9594) | 评论 (11)编辑 收藏

浅谈网页游戏

前阵子我一直在研究基于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将注定成为网页网络游戏技术 的主角。


posted @ 2008-01-22 16:10 CoffeeCat 阅读(1092) | 评论 (6)编辑 收藏

如何在WMP中加载idx sub字幕

今天帮同学解决了avi电影加载字幕的问题,简单记录一下,希望对大家有用~

方法:
1:先将idx和sub文件和avi文件放在一起
2:将idx和sub文件重命名,名字和avi的文件名一致
3:用Windows Media Player打开avi文件,点击播放菜单->字幕->开,就可以看到字幕显示出来了。

CoffeeCat
2008-1-1

posted @ 2008-01-01 23:07 CoffeeCat 阅读(5518) | 评论 (0)编辑 收藏

仅列出标题
共9页: 1 2 3 4 5 6 7 8 9 
<2024年3月>
252627282912
3456789
10111213141516
17181920212223
24252627282930
31123456

导航

统计

公告

常用链接

留言簿(203)

随笔档案

收藏夹

搜索

最新评论

阅读排行榜

评论排行榜