多层压缩等于不压缩?

February 4th, 2010 snaill No comments

从网上下了一个东西,zip的压缩包

解压是55个zip压缩包

再解压是55个rar的分卷压缩包

再解压才是真正的文件

一般压缩文件就是为减小文件个数,压缩文件占用的空间,那么如此多层的压缩当然是目的当然是进一步减少文件的大小了,那么效果如何呢?以此为例,如下表:

原文件大小

273,156,452 字节

Zip压缩

272,770,342 字节

7z压缩

274,608,539 字节

多层压缩

273,152,780 字节

大概是因为原文件本来就做过压缩的缘故,多层压缩的结果只使文件缩小了不到4K,而zip单次压缩的结果更优。

当然这只是一个特例,但也说明多层压缩未必能进一步缩小文件大小,所以请勿再作如此麻烦的事情了:)

iPad在中国前景堪忧

January 29th, 2010 snaill 2 comments

随着27号的苹果发布会,一直在迷雾中的苹果平板电脑iPad一下子进入人们的视线。

今天收到苹果的邮件,发现iPod登陆苹果的中文网站。看过后发现和早间在Twitter上听到的印象不同。又重新对照了英文的网站,才发现中文网站删减了某些介绍:iPad

没有iBook,iPad最重要的功能,但明显苹果没能在国内找到有力的图书资源的支持

没有导航功能,大概是苹果还没有搞清楚是否要和3G网络提供商合作,因为在中国,一旦触及通讯领域,就意味着是不是要阉割WIFI的问题,对iPad来说就是要WiFi还是要3G的问题。鉴于目前中国3G的普及状况,苹果很可能只在国内销售无3G的版本。没有3G,导航功能还有什么用呢?

其他如iTunes,YouTube都是老问题了,本来就在国内不能使用,自然也不可能介绍。

奇怪的是,不管是中文还是英文网站都没有提到iWork,实际上,就平板电脑来说,直接通过手对文档进行批注是最基础的功能,也是区别于一般笔记本电脑的很酷的功能,不知道是苹果没有意识到,还是因为这些功能都需要另外付费(每个组件据说是$9.99)而故意被忽略了。

从iPad出现起,就褒贬不一,不过毕竟还有如iBook这样的特殊应用,但在国内仅从苹果网站的宣传来说,它真的就是个大号的iTouch,实在让人无法提起购买的欲望了。。。。。

iPad英文介绍

iPad中文介绍

Categories: 七嘴八舌 Tags:

又上了名字空间的套

January 25th, 2010 snaill No comments

在做一个XML的XSL,原XML如下:

<?xml version="1.0" encoding="utf-16"?>
<book version="5.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns="http://docbook.org/ns/docbook">
  <info>
    <title>test</title>
    <author>
      <personname>
        <othername>Unknown</othername>
      </personname>
    </author>
    <bibliosource>Unknown</bibliosource>
  </info>
</book>

制作的XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="info">
        <xsl:value-of select="title" />
    </xsl:template>       
    <xsl:template match="/">
        <xsl:apply-templates select="/book/info" />
    </xsl:template>
</xsl:stylesheet>

结果是没有任何输出,郁闷了好久才发现是因为忽略名字空间造成的,注意在XML中定义了xmlns,而在XSL中没有对应的定义,导致XPath无法正确地找到节点。解决的办法很简单,只要在XSL中加入缺省定义就可以了,如下:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://docbook.org/ns/docbook">

早先在使用XSL生成XHTML的时候,也有过一次因为名字空间冲突导致无法输出的问题,看来名字空间这个东西真不是个善茬,要时时刻刻得小心谨慎阿

Categories: Jeebook, XML Tags: , ,

Nexus One和全球化

January 12th, 2010 snaill 2 comments

周末订了台Nexus One,也就是所谓Google Phone,过程可谓曲折。

由于国内政策所限,直接访问Google网站无法看到购买的按钮,只好翻墙登录

由于Google采用Google Checkout处理支付,而Google Checkout不对国内开放,只好冒充香港用户,好在信用卡是VISA的,地址只要是英文就可以通过。

由于Nexus One只支持送货到美国,英国,香港,新加坡,只好先寄到英国再转回来。

刻字刻的“Hello, World”,程序员的经典名句。

没要充电器,将近20美金,回头肯定20人民币就可以买到山寨的

DHL邮费28美元,貌似到香港才要27,也不知道是不是真的比较近:)

一切就绪,结果Google的系统出错了,无法确认订单,重来一遍才算搞定。据说订单提交后15分钟内可以取消,不过貌似老美还在睡觉,到第二天才看到扣费的短信。

一部Nexus One,大陆生产,台湾出品,美国销售,邮寄英国,转发大陆,好大的一个轮回,这就是所谓全球化,要无谓的产生多少碳排放?

何况,岂止这一部手机,成千上万的商品不都是如此?人们总在妄言低碳经济,怎么可能实现?

XHTML解析的实体问题

January 3rd, 2010 snaill No comments

我在《集成Html Tidy》一文中说过使用HtmlTidy转换HTML以方便使用XML解析器解析,事实上,并没有那么简单,随便解析几个XHTML就会碰到解析异常的问题,错误是“Reference to undeclared entity ‘nbsp’”。

查找原因发现,在XML中,除了&lt; &gt; &amp; &apos; &quot;以外,其他如&nbsp;之类的实体必须通过DTD或其他方式定义。Html Tidy转换出的XHTML并没有显式定义这些实体,而是采用类似以下的定义:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

在这个DTD中会定义如&nbps;之类的实体,但由于需要到W3C的网站上去获取这些定义,所以XML解析器默认会忽略这些定义,就导致没有定义的异常。

不过在.net中提供了XmlResolver类帮助处理这种情况,而我们需要做的就是重写这个类,并将XHTML中定义的DTD重新指向我们指定的某个位置,如上的情况操作如下:

1. 下载http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd

2. 将下载的dtd作为资源放入程序中

3. 重写XmlResolver类,增加判断,当传入的路径为"-//W3C//DTD XHTML 1.0 Transitional//EN" 时就以流方式返回资源中的DTD

4. 创建XmlReader,并将重载的XmlResolver设置在XmlReader中

5. 使用该XmlReader装载解析XHTML

完成以上步骤,再解析XHTML就不会再有异常出现了。当然XHTML的DTD定义不止这一种,为了兼容起见,最好将所有的DTD定义都按以上的步骤加入程序中。

具体实现代码可以参考我的开源项目:Page Releaser

UrlRewritingNET实现URL Rewrite

December 30th, 2009 snaill No comments

在asp.net中实现URL Rewrite,除了IIS本身带的URL Rewrite Module以外,还有很到其他的解决方案,比如UrlRewritingNET

UrlRewritingNET号称除了文件扩展名Rewrite需要IIS支持以外,其他所有操作都不需要IIS设置,这当然对虚拟主机的网站来说是非常便利的。

下面看看怎么来部署UrlRewritingNET:

1. 首先将下载的dll放置到bin目录

2. 修改Web.config,增加UrlRewritingNET的相关配置如下:

<?xml version="1.0"?>
<configuration>
    <configSections>
        <section name="urlrewritingnet"
                 requirePermission="false"
                 type="UrlRewritingNet.Configuration.UrlRewriteSection, UrlRewritingNet.UrlRewriter"/>
    </configSections>
    <urlrewritingnet rewriteOnlyVirtualUrls="true"
                   contextItemsPrefix="QueryString"
                     defaultProvider="RegEx"
                     xmlns="http://www.urlrewriting.net/schemas/config/2006/07">
        <rewrites>
            <add name="category"
                 virtualUrl="^~/category/(.*)"
                 rewriteUrlParameter="ExcludeFromClientQueryString"
                 destinationUrl="~/index.html?category=$1"
                 redirect="Application"
                 ignoreCase="true"/>
            <add name="book"
                 virtualUrl="^~/book/(.*),index.xml"
                 rewriteUrlParameter="ExcludeFromClientQueryString"
                 destinationUrl="~/reader.html?book=$1"
                 redirect="Application"
                 ignoreCase="true"/>
            <add name="categoryAPI"
                 virtualUrl="^~/api/category/(.*)"
                 rewriteUrlParameter="ExcludeFromClientQueryString"
                 destinationUrl="~/api/Category.ashx?path=$1"
                 ignoreCase="true"/>
            <add name="bookAPI"
                 virtualUrl="^~/api/book/(.*)"
                 rewriteUrlParameter="ExcludeFromClientQueryString"
                 destinationUrl="~/api/Book.ashx?path=$1"
                 ignoreCase="true"/>
            <add name="metaAPI"
                 virtualUrl="^~/api/meta/(.*)"
                 rewriteUrlParameter="ExcludeFromClientQueryString"
                 destinationUrl="~/api/Meta.ashx?path=$1"
                 ignoreCase="true"/>                
        </rewrites>
    </urlrewritingnet>
    <system.web>
        <httpModules>
            <add name="UrlRewriteModule" type="UrlRewritingNet.Web.UrlRewriteModule, UrlRewritingNet.UrlRewriter"/>
        </httpModules>
    </system.web>
</configuration>

3. 嵌入Rewrite规则,在<rewrites>中。virtualUrl是正则表达式的虚拟URL,destinationUrl是目标的URL。如果表明redirect,则UrlRewritingNET会通过HTTP 301,302重定位,浏览器显示的网址会有所变化

4. 需要注意的是,需要添加Global.asax,UrlRewritingNET才会生效

HTML页面之间的参数传递的局限性

December 28th, 2009 snaill No comments

动态网页传递参数比较简单,如果想在HTML之间传递参数就需要一点技巧,摘录两种方法如下:

采用字符串解析的:

/*
*函数功能:从href获得参数
*sHref:   http://www.cscenter.com.cn/arg.htm?arg1=d&arg2=re
*sArgName:arg1, arg2
*return:  the value of arg. d, re
*/
function GetArgsFromHref(sArgName)
{

     var sHref= document.location.href;
    var args  = sHref.split("?");
    var retval = "";
    if(args[0] == sHref) /*参数为空*/
    {
         return retval; /*无需做任何处理*/
    } 
    var str = args[1];
    args = str.split("&");
    for(var i = 0; i < args.length; i ++)
    {
        str = args[i];
        var arg = str.split("=");
        if(arg.length <= 1) continue;
        if(arg[0] == sArgName) retval = arg[1];
    }
    return retval;
}

采用正则表达式的(注意:tmp=rs不是书写错误):

function getQueryString(name){
    var url = document.location.href;
    var rs = new RegExp("(^|)"+name+"=([^\&]*)(\&|$)","gi").exec(url), tmp; 
    if (tmp=rs)
        return tmp[2];
    return ""; 
}

通过解析document.location.href中保存的路径获取传递的参数,在一般情况下没有问题,但如果采用URL Rewrite,情况就不同了。

比如,设置规则将http://jeebook.com/store/category/test/转义为http://jeebook.com/store/index.html?path=test/,这时document.location.href会返回http://jeebook.com/store/category/test/,而不是我们希望的http://jeebook.com/store/index.html?path=test/,于是就无法实现参数传递的效果了

解决办法是在URL Rewrite规则中设置Redirect,URL Rewrite会通过HTTP 301或302重定位新网址,但代价是浏览器中无法显示原来的虚拟路径了。

看来,HTML毕竟还是有局限性的:〉

实现HTML的简单压缩

December 21st, 2009 snaill No comments

PageReleaser需要一种HTML的压缩算法,Google了很久,发现如果只是简单去除空白和注释的话,使用XLinq就可以轻易的实现

先看看MSDN是怎么说的:

一种常用方案是读取缩进的 XML,在内存中创建一个没有任何空白文本节点(即不保留空白)的 XML 树,对该 XML 执行某些操作,然后保存带缩进的 XML。在序列化带格式的 XML 时,只保留 XML 树中有意义的空白。这是 LINQ to XML 的默认行为。

另一个常见的情况是读取和修改已经有意缩进的 XML。您可能不想以任何方式更改这种缩进。若要在 LINQ to XML 中执行此操作,您要在加载或解析 XML 时保留空白,并在序列化 XML 时禁用格式设置。

简单的说,XDocument载入时,默认使用LoadOptions::None,自动去掉XML的空白;保存时,默认使用SaveOptions::None,自动格式化XML。

也就是说,使用XDocument将一个HTML文档打开什么也不作就保存,其实等于实现了HTML的格式化。

而如果在保存时,使用SaveOptions::DisableFormatting参数,看似要保存XML的空白,由于载入时所有空白都被删掉了,其实等于删除了所有空白,于是去掉空白就这样实现了。

至于删掉注释也很简单,只是需要注意,一般页面嵌入JavaScript会使用注释节点包裹,需要例外处理。

整个HTML压缩代码如下:

var nodes = from s in doc.DescendantNodes()
where s.NodeType == XmlNodeType.Comment &&
string.Compare( s.Parent.Name.LocalName, “script”, true ) != 0
select s;

nodes.Remove();
doc.Save( sm.OutputPath + “index.html”, SaveOptions.DisableFormatting );

简单吧,不过HTML不能直接使用XML解析器,需要预先转换为XHTML,点击察看转换实现。

P.S. 需要注意的是,如果在Load函数中使用了XmlReaderSettings,则LoadOptions参数会无效,是否压缩取决于XmlReaderSettings中的参数设定。

Categories: C#, PageReleaser, XML Tags: , ,

开源项目:Page Releaser

December 18th, 2009 snaill No comments

使用js框架+Ajax模式的开发,总会造成大量的js文件导致网站传输效率降低,尤其在网络状况不佳的环境很容易出现整个网页无法使用,就如IE的那个经典错误,对象不支持此属性或方法。

js压缩合并的工具很多,我也基于JsMin做过JsMin#。不过因为调试的需要,仍然需要维护一个调试用得HTML,里面引用所有未压缩的js;再维护一个发布用得HTML,用来引用合并后的js。每次更新网页都非常不方便。

此后,开始构思更好的方法,于是有了Page Releaser的构想。

Page Releaser借鉴了C++中Release的概念,通过解析HTML提取js和css信息,并对它们进行压缩,合并,嵌入,再依照处理结果重新构建HTML,最终生成一套完整的发布版本。之所以叫Page,是因为它每次只处理一个HTML。(本来打算叫WebReleaser,但多HTML会牵涉到资源网页间共用的问题,比较复杂,自动化结果会很难评估。不过好在,像ExtJS这样的大型框架,任何应用一个HTML就够了:)

Page Releaser的终极目标是将包含一个HTML,N个JS,N个CSS,N个图片的网站,最终压缩成一个HTML和一个图片,以最大的减少浏览器因为建立连接造成的效率浪费。

当然,浏览器建立最少的连接并不意味着网站就有最优化的效果,比如一张1000*1的图片和一张1*1000的图片无论怎么合并,生成新图片都会比原来的图片大得多,所以Page Releaser也提供各种参数以便产生针对性的最好效果。

目前放出的版本只是实现了js的压缩,合并,嵌入以及css的合并,嵌入,其他功能将逐步加入

Page Releaser安装

当然按照惯例,小工具一概开源,大家也可以自行下载代码编译:

Page Releaser源码

新闻业是新制造业?

December 16th, 2009 snaill No comments

继旗下报业屏蔽Google引起访问量大跌之后,默多克又撰文为新闻业鼓劲,他要求传媒企业要提供人们想要的新闻以应对竞争,抨击汇集者(如Google)的高利润,提出优质内容不是免费的的观点以依靠广告的旧模式。

在新闻业受到经济危机冲击大量倒闭的背景下,默多克这一系列举动,让我不禁将新闻业和中国制造业现状作了个对比。

如郎咸平老爱讲的,中国制造业现在受到的挑战,是因为美国只把整条产业链中价值最低的制造部门给了中国,而他们掌控了产业链其它最有价值的五部分,包括采购、仓储、订单处理、批发、零售。所以在整条产业链上,即使如血汗工厂的廉价劳动力也仍然没有产生优势。

制造企业地位的下降,从工业革命开始就开始了。工业革命直接导致物资由匮乏走向过剩,过剩导致生产制造的价值降低,这是客观规律,所以东莞的玩具制造商永远也无法做到如沃尔玛这样大型零售商的利润率。

同样的,在互联网出现后,信息开始匮乏走向过剩,信息的制造企业如新闻业地位下降也成为必然。尤其是搜索引擎广泛使用后,Google这样的企业通过汇集信息走到了前台,就像沃尔玛一样直接向用户兜售信息,而新闻业则开始逐渐远离新闻受众。

试想,当一个新闻网站大部分的流量都来自Google,就意味着大多数受众都是从Google资讯,Reader,搜索引擎链接过来的,那么这些人还会访问的是什么新闻网站吗?如果这些新闻网站再通过Google广告来赚取利润,则新闻网站就变得和东莞的玩具制造商被沃尔玛这些大型零售商控制一样,完全被Google控制。

结果是,Google占据产业链上的五,而新闻业则只占据一,用不了多新闻业就要向中国的血汗工厂看齐了。

新闻业如何应对这样的趋势呢?郎咸平对中国制造业开出的药方是,要从一走向六,完全占据整个产业链。而默多克恰恰也是这么做的,屏蔽Google就如同东莞的玩具制造商不再像沃尔玛兜售商品,优质内容不再免费则是开始创立自己的模式和品牌。

当然现在鹿死谁手还很难说,不过,默多克的资源远多于东莞的玩具制造商,或许胜算会大很多吧