2009年3月31日星期二

淘宝API

下面一段文字摘自爱枣报: 现在网上购物越来越流行,淘宝开店也成为一种潮流,在淘宝开放API之后,围绕淘宝商城的网络应用也正在成为一条新的产业链。而在美国,苹果的iphone应用程序商店开业的最初几个月就创造了800万次的下载,迄今已经推出了1万多个应用程序,很多全世界各地的程序开发员也加入到了"Apple"树下吃苹果的行列。无论你是因为经济寒冬暂时"结构性失业",还是即将踏出大学校门暂时没有找到合适的归宿,如果有这方面的才能,不妨试试淘宝应用,说不定这就是你的第一桶金。


越来越多Web网站发布API,Google、Yahoo、Twriter等都有。苹果iphone的Store模式,是非常成功的,让一部分程序员获利颇丰。苹果提供了一个商业平台,程序员可以在平台上发布和维护自己的应用产品,苹果把这些来自程序员的应用产品推销给用户,用户在平台上查找和购买自己需要的应用产品,苹果从中收取提成。
1)不知道淘宝是否也提供这么一个平台?
2)在iphone平台上利用Apple提供的API可以开发许多实用的应用产品,那么利用淘宝API能开发那么广泛的产品吗?淘宝API提供了哪些功能?
3)淘宝的用户可以分为普通消费者和商家两类。淘宝API是针对哪类?两类用户应该有不同的需求。针对两类用户可以开发什么有价值的应用呢?有价值,用户才会花钱购买。
4)大部分来淘宝的普通消费者都是图便宜图便利,让他们在多花点钱可能就比较难了。不过按照图便利的思路,还是能开发许多应用供消费者使用的,但是付费,似乎比较难。或者循着社会化网络的思路,可以整合其他Web网站的API,完成一些分享,比如消费者购买了一台豆浆机,可能他要把这件事发布到blog或SNS网络上,并附加评论。
5)我觉得针对商家的应用更有盈利的可能。淘宝里的商家,所谓网店的店主,都是通过淘宝赚钱的,让赚钱的人花点小钱应该是比较容易的。如果有什么软件能帮店主增加销售额,应该对店主很有吸引力。传统的CRM系统是否可以借鉴?网店也是微型企业,店主也需要维护客户关系啊,CRM主要是个销售和营销用的,这些店主也都需要。然后再提供各类报表,财务,call center,BI和BAM等功能,哈哈,让小小的网店也用上先进的CRM系统。这样的CRM系统可以通过On Demand或者SAAS以服务形式提供给店主,每月费用很低,比如100块钱,这样店主就不用自己部署和维护,轻松上手,小成本投入,也免除桌面程序被破解的烦恼。优秀的CRM厂商主要是国外跨国公司,它们现在也很重视CRM On Demand的市场潜力,但是应该是不屑于这个小市场的,而且对网店店主来说,服务费用太高了。最大的竞争对手可能来自淘宝。因为淘宝可能自己打算做这一块,也许目前淘宝已经为店主提供类似的后台分析功能了。

APG all hands meeting

今天早上整个APG召开all hands meeting,各位manager介绍了各自团队在过去一年的成就以及接下来的计划。这是我来OARDC两年来第一次参加这么个all hands meeting。以前在微软中国技术中心实习时是每个月一次all hands meeting的,由于呆的时间不长,对微软的产品以及各部门的人员都不是很熟,因此虽然参加了几次all hands meeting,还是对各部门在做什么产品不甚了解。这次的all hands meeting,还是有些收获的。
1)通过各团队manager的介绍,基本明白每个team,每个人在做什么项目和产品了。其实每个员工和团队在公司内部的shiji blog都有一个自己的blog,每周的工作总结和每次会议记录都发布在blog上。如果平时留意去阅读一下这些blog,对他们的工作内容和职责就能了解个大概。公司内部的blog系统还是一种十分有效的管理方式,可以分享知识,记录历程。
2)各manager都用英语介绍了各自的team,基本上英语表达能力都是不错的。Sherly的英语还是最容易听的,语速很慢,吐字很清晰,很流畅,不停顿。Pascal的带点法国腔的英语,今天听来也不怎么费力。其他manager的英语稍微有点不流畅,语句老是出现"嗯,阿"之类的口头禅。在外企,英语口语的能力非常重要,就像国企里的背景,决定了升迁。因为在外企,首要的是和外国同事沟通。
3)这次会议给我印象较深的是Joey以及他做的报告,我想OARDC的老大Pascal也是这样的。会议的主角是各位manager,他们介绍团队,同时在领导面前展示自己的才能。首先GCI是一个比较新奇的项目,大家都不大清楚它是干嘛的,因此大家带着好奇。其次是Joey的演讲内容比较有特色。怎么在几个manager里脱颖而出,在领导面前留一个好印象?标新立异,与众不同是一个好方法。Joey的演讲内容与众不同的地方有用一段Video介绍自己的团队成员,以及最后用一个现场demo让Pascal也参与进来。而其他manager的初始想法都是在页面上罗列一下团队成员,用几个截图展示一下他们的team所做的工作。图片当然没有现场的demo令人印象深刻,而且让Pascal也参与到demo里来。最后Joey的反应速度还是不错的。那段Video由于网络问题,没有成功播放,于是他立刻改叫团队成员起立让大家认识一下,可见反应速度比较快,避免了现场的尴尬。后来回答台下人向他提问时,回答时很有条理,"第一点……,第二点……"。他认真了,努力了,他抓住了机遇。看来做什么事都得认真。
4)这次的all hands meeting应该是Sherly首次筹划的,和各位manager做了精心的准备,是比较成功的。可能以后all hands meeting会成为一个例行会议,每季度一次。此外Sherly打算每月举办内部演讲,分享知识,也是一个行之有效的团队管理手段。佩服Sherly的管理能力。

2009年3月27日星期五

考虑摊低

今天美邦服饰出年报,10送5派3,走势还算平稳,早盘冲高到3%多,尾盘涨幅不到1%。报喜鸟继续萎靡,本周继续缩量震荡。本以为美邦服饰能借年报飚一下,从而带动一下服装板块。美邦股价高估是肯定的。但是它对报喜鸟的上升空间还是有很大影响的。如果美邦一直在25块徘徊,报喜鸟是到不了20的。其实并不是只有报喜鸟乌龟爬,服装板块中的美邦服饰,七匹狼都是恨铁不成钢。除了服装板块,白酒板块也是涨幅很小的,探了一次底又探一次底,但是就是没跌穿去年11月份的大底。因此我觉得那个大底将会是绩优白酒股这次熊市的底,所以买入后可以睡觉去了。可见这波反弹,防御性板块都是涨幅较小的。一是本来就抗跌,二是不像周期性行业和实体经济息息相关,一会利好,一会利空,消息满天飞,很是吸引眼球。选择防御行业,就是选择孤单和坚守。白酒绩优股继续躺着,给我加仓的机会,不亦乐乎。我是觉得白酒板块的上涨潜力是要比服装板块大的,但是持有报喜鸟都2个月了,选择现在调仓,有点不甘心。持仓结构是需要调整,要加大白酒板块的比重。很多人对中线持有的股票,采用T+0或短线波段操作摊低成本,我觉得这对防御型板块还是比较可取的。防御型板块的走势经常是箱型震荡,不会大起大落,偶尔大起时卖出部分,偶尔大落时买回部分,倒是能摊低成本。反之周期型行业走势经常是一跌再跌没有最低或者一涨再涨,摊低常常成为一补再补最后深套或者一下子被逼空。有人经常说对这种那种股性的股票该如何操作。所谓股性,是否就是指防御型和周期型,或者和它们有很大关系。学学如何对防御型股票进行摊低成本。摊低应该把自己的持仓划分为两部分

FastExcel阅读笔记

FastExcel: Version 0.3.3

一、Compound File类设计
和复合文档有关类存放在如下几个package:
edu.npu.fastexcel.compound.io; 把对操作系统文件的IO操作封装成Reader和Writer,主要基于RandomAccessFile。为了提高文件读取速度,使用了Memory Mapped File,基于MappedByteBuffer。
edu.npu.fastexcel.compound.stream; 将Reader和Writer封装成ReadableStream和WritableStream。这里的Stream类就是对应于复合文档里的Stream。
edu.npu.fastexcel.compound; 将Stream包装成StreamReader和StreamWriter,比如SectorStreamReader就是读取复合文档中的扇区。最后提供复合文档的FileReader和FileWriter。
这部分的类设计和Java的IO类设计很类似,再查看一下Java的IO类设计,体味一下,加深理解和印象
此外这部分还包含一个SummaryInformation类,这个类有点独立,对于Excel读写来说是可有可无的。当初作者可能一时兴起,把它也写出来了。Office文档一般都有Summary Information Stream。加上这个类,整个Compound File类体系就比较完整了。


二、BIFF8类设计
1)BIFF8中比较有用的Record类别:
BOF,EOF:Substream的开始,结尾
SST:Shared String Table,存放所有出现在Worksheet中的字符串
SHEET:存在于Workbook Globals Substream,代表Workbook中的一个Sheet,描述了该Sheet的名字,类别,状态,偏移位置等信息。
DIMENSION:包含当前Sheet的有效范围,起止行号,起止列号。
LABELSST:单元格的字符串内容通过索引指向SST中的某个字符串。
2)Record类设计:
所有支持的BIFF8 Record类别都有对应的Record和Parser(RecordParser)类。比如SSTRecord,SSTParser。Record类用来处理写入,Parser类用来处理读取。
Record类组织成如下几个package:
edu.npu.fastexcel.biff.record; 处理通用的Record类别,可能出现各个Substream里,比如BOF
edu.npu.fastexcel.biff.record.globals; 处理那些只会出现在Globals Substream里的Record类别,比如SHEET
edu.npu.fastexcel.biff.record.sheet; 处理那些只会出现在Worksheet Substream里的Record类别,比如DIMENSION
edu.npu.fastexcel.biff.record.cell; 处理和单元格密切相关的Record类别,比如LABELSST
RecordFactory提供方法返回各种Record类的实例。RecordFactory使用Singleton模式。实现Singleton模式的方法是采用静态内嵌类的静态字段,不知道为什么这么实现?有什么好处?实现代码片段如下:


static class InstanceHolder {
static RecordFactory instance = new RecordFactory();
}

类似Parser类也组织成如下几个package:
edu.npu.fastexcel.biff.parser; 处理通用的Record类别,可能出现各个Substream里,比如BOF
edu.npu.fastexcel.biff.parser.globals; 处理那些只会出现在Workbook Globals Substream里的Record类别,比如SHEET
edu.npu.fastexcel.biff.parser.sheet; 处理那些只会出现在Worksheet Substream里的Record类别,比如DIMENSION
edu.npu.fastexcel.biff.parser.cell; 处理和单元格密切相关的Record类别,比如LABELSST
所有的Parser类都在ParserFactory里登记,存放在一个Map里,Map的键就是Record的类型号,值就是一个Parser对象。这里没有使用Singleton模式,反而有点Factory模式的味道。读取Worksheet Substream时有两种模式:全读取模式和事件模式。全读取模式就是在访问某个Sheet里的某个单元格之前,该Sheet的内容都已经读取完毕,访问时,就是简单的返回内容。事件模式就是在解析一个Sheet的过程中,解析出一个单元格就触发事件,客户程序可以按意愿监听事件。这两种模式有点类似XML的两种解析器,DOM和SAX。显然,事件模式采用监听器模式。监听器接口是SheetReadListener。抽象类SheetReadAdapter implements SheetReadListener,对监听器提供默认实现,这种实现方法应该叫 Adapter模式吧,类似于Java AWT里的MouseEvent,MouseEventListener,MouseAdapter。EventBasedSheetStream是事件的触发器,它有一个字段保存当前的监听器。监听器的设置是通过get和set方法,而不是add和remove方法,可见只支持一个监听器,不支持事件的多播。也许这个情境下的多播没啥意义。
3)BIFF8 File类设计
主要是三个package:
edu.npu.fastexcel.biff; 读取和写入都公用的一些东西,这里只有所有的Record Type常量,放在Types类中。
edu.npu.fastexcel.biff.write; 写入相关的几个Writer。Worksheet Substream和Globals Substream都有各自的Writer。BIFFWriter包含一个WorkBookGlobalsStreamWriter,而WorkBookGlobalsStreamWriter又包含一个SheetStreamWriters的list。BIFFWriter就是利用各个Substream的Writer来实现写入的。当然这些BIFF的Writer最终都要写入到一个复合文档的一个Worksheet Stream里,复合文档的Worksheet Stream的Writer又通过Java IO写入物理文件。也就是说BIFF的Writer使用了Compound File的Writer。这里还没有Excel文件和复合文档的概念,有的还只是Writer和Reader的概念。Excel文件是一个复合文档,看起来设计时要采用继承。而这里只有Writer和Reader的概念,使用的却是组合。我想用继承也是可以的,不过这里用的是组合,组合有组合的好处。有哪些好处呢?
edu.npu.fastexcel.biff.read; 读取相关的类,设计思路和write部分相似。一般来说read部分的类会稍微比较多,处理稍微复杂,因为一般要读取的文件都是MS Excel产生的标准xls文件,内容比较全,包含各种额外的信息,比如格式信息,字体信息。写入生成一个xls文档就比较简单了,只把文本内容写入就行。MS Excel打开这样的文档会用默认的格式展现数据,重要的是文本内容显示出来了,而并不在意文本显示出来是怎样的。


三、用户API设计
这里说的API就是指提供给最终用户使用哪些类。最终用户可能不关心底层的实现细节,他想要了解的是,一个Excel有几个Sheet,每个Sheet有什么内容。因此最高层的API包装应该只是提供诸如Workbook,Sheet等概念。API在edu.npu.fastexcel这个package里,Workbook,Sheet都是接口,FastExcel类的设计应该使用了Facade模式,仅仅提供两个方法,创建一个可读取Workbook和创建一个可写入Workbook,把具体如何使用Writer和Reader实现所需功能的细节全部隐藏起来。这个package里还包含监听器接口SheetReadListener,因为这个接口也是用户所关心的。如果用户程序打算监听事件,就需要实现这个接口。在这个package还有ReadableWorkbook、WritableWorkbook、ReadableSheet、WritableSheet类,我感觉可以把它们放到其他package里更好。


四、建议
1)在每个package下面都包含一个描述文件,描述这个package里的类是干嘛的,就更清晰了。
2)我感觉可以把edu.npu.fastexcel这个package下的ReadableWorkbook、WritableWorkbook、ReadableSheet、WritableSheet类,放到其他package里更好。
3)是否应该使用一个示意为私有package的前缀,从而将一些包含具体实现细节,不易于最终用户重用的package标明为私有,比如在edu.npu.fastexcel下建立一个edu.npu.fastexcel.private子package,然后让Compound,BIFF8等实现全部放到edu.npu.fastexcel.private包下。因为提供诸如可重用的Compound File类并不是作者的意图。

2009年3月26日星期四

该跌不跌,该涨不涨

今天早盘市场萎靡不振,跌多涨少,报喜鸟却红着,微涨1%。下午14:30过后,大盘发飙,劲升50多点,报喜鸟却依然只涨2%。该跌不跌,该涨不涨,按照经典理论来看,有主力在洗盘吸筹。但是吸了那么久,还没吸够吗?

Excel文件格式(BIFF)

Excel的文件格式是BIFF(Binary Interchange File Format)。从Excel97 - Excel2003使用的是BIFF version 8,可是说BIFF8是目前最广泛使用的Excel版本。BIFF8基于微软的复合文档格式。Excel文档的内容存放在一个Stream里。一个新建的空白Excel文件,一般包含Root Storge,Workbook Stream,<05H>SummaryInformation Stream,<05H>DocumentSummaryInformation Stream。Workbook Stream就存储了Excel的内容。把整个Excel文件叫Workbook,Workbook里至少有一个Worksheet。Excel文件不仅存放Excel的文本内容,还存放一些格式,比如字体信息,颜色。Excel的逻辑结构可以用下图表示:

Workbook globals里就记录了整个Workbook公用的东西,比如格式,字符串常量,文档保护等。worksheets,workbook globals都是存储在Workbook Stream里,可以把它们看做是substream。各个substream按一定顺序出现在Workbook Stream里,如下图所示:

图中所示,Globals Substream是必须的,而且至少保护一个Sheet Substream。那么这些Substream是如何区分开的,如何知道一个Substream从文件的哪个位置开始,哪里结束呢?这得从BIFF8描述信息所采用的格式来说。这里说的"信息",包含很多,比如格式信息,位置信息,文本信息,图片信息,宏代码信息,等等。这么多信息要记录,BIFF8是采用Record的方式来记录的。一个Record描述一个信息。因此有很多种Record。因此Record Type肯定是Record数据结构的组成部分。Record是不定长的,种类非常多,各个种类的内容格式千差万别。但是基本遵循如下的结构:

结构包含两部分,Record Header和Record Data。Record Header部分的前2字节是Record Type,然后是2字节描述Record Data的长度。文档给出了几乎所有的Record Type,针对每种Record,描述了Record Data里各字节的含义。Substream的开始和结束,就是采用BOF和EOF这两个Record Type。也就是说在Workbook Stream是Record序列,一个Record接着一个Record,有些BOF的record表示接下来要描述一个Substream了。因此处理程序可以一个Record一个Record的读取,先检查读入的Record的Type,如果不认识,那么就不处理Record data部分,如果认识就解析Record data部分的含义。Excel的版本是不断升级的,补丁是不断更新的,新的版本,新的build就可能有新的Record Type。因此旧版本的Excel打开高版本的xls文件,有些Record就无法识别,但是不影响基本数据的读取。FastExcel就是根据这个原理,只处理一些和文本内容相关的必需的Record Type,像格式之类的Record就不处理了,因此就Fast了。
当一个Cell的内容为字符串常量时,BIFF8一般把这个字符串常量用SST这种Record记录在Global Substream,然后在Sheet Substream里使用LabelSST这种Record引用这个字符串。LabelSST这种Record的Record Data部分就包含了行号,列号,字符串索引号(index)等信息。查看文档,可知LabelSST类型的Record Header的Identifier是00FD(hex),size是10,Record data结构如下图所示:

FastExcel的项目主页也说了它们只实现了如下的Parser来处理一些Record,仅仅是针对文本内容,BIFF8的Record类型可是几百个。这里的BOFParser就是处理BOF类型的Record,LabelSSTParser处理LabelSST类型的Record。
* BOFParser
* EOFParser
* BoundSheetParser
* SSTParser
* IndexParser
* DimensionParser
* RowParser
* LabelSSTParser
* RKParser
* MulRKParser
* LabelParser
* BoolerrParser
* XFParser
* FormatParser
* DateModeParser
* StyleParser
* MulBlankParser
* NumberParser
* RStringParser
BIFF8里多字节数据,比如4字节整数,2字节整数,Unicode都是采用Little-Endian的存储方式。

2009年3月25日星期三

微软复合文档格式 (Compound Document)

今天看到一个FastExcel的开源项目,它能够使用纯Java代码读取Excel文件的文本内容以及写入内容保存为Excel文件。这项目的作者应该是一个中国人,因为项目源代码中包含的JUnit测试代码里居然有中文数据。把项目的源代码导入到Eclipse编译,运行了附带的测试用例。源代码里的package开头是edu.npu。baidu一下,npu好像是西北工业大学。作者在项目的简介里介绍了代码的工作原理是依照Excel的文件格式,直接进行读取。而Excel的文件格式是基于复合文档(Compound Document)的。项目主页上有链接给出复合文档格式Excel文件格式,都是OpenOffice社区整理的。
复合文档简单的说就是在一个文件里可以内嵌其他各种文档,这些内嵌的文档还具有目录结构,可以说复合文档格式就是在一个文件里面实现一个文件系统。从逻辑上说复合文档包含Storage和Stream。Storge相当于我们熟知的操作系统文件系统里的目录,Stream相当于文件。下图就是复合文档的逻辑示意图。和操作系统的文件系统类似,同一个Storge下的Stream不可以重名,不同Storage下的则可以。

其实这个图的内容,很久之前我就了解了,而且很好理解。当初看MFC书籍讲复合文档的时候就在这个层次上。自己也没深究过要实现这样的逻辑结构,物理上该如何存储。今天特地阅读了这个文档格式,25页,不是很长,边阅读边查看一个Excel文件的物理存储结构,这样更好理解。
物理结构图:

开始是一个文件头(Header),固定长度512字节。然后是一个接一个的扇区(Sector),大小是可变的,一般是512字节。这里的Sector可以类比为磁盘上的扇区,反正就是一块文件空间。一个复合文档,除了文件头就是扇区。因此复合文档的内容数据主要是存放在扇区里的。此外有些扇区得用来存储一些元数据,描述扇区和扇区之间的关系,哪些扇区是用来干嘛的,那几个扇区组成一个Stream。每个扇区有一个标识符,也就是编号,从0开始,依次递增。扇区的编号用有符号的4字节整数来表示,这样在内部就可以引用了。扇区号可以是负数,几个负扇区号的特殊含义是:

就像磁盘文件系统,一个文件有多个块组成,在复合文档里,一个Stream也是由多个Sector组成。那么多个Sector的顺序是怎么样的?一个Stream到底有几个Sector组成呢?这是通过Sector Allocation Table(SAT)来实现的。SAT顾名思义就是跟踪Sector的分配情况。SAT也得需要空间来存储啊!当然也是存储在Sector里的。可以说SAT也是一种特殊的Stream,它描述一个Stream拥有哪些Sector。那么谁描述它自己拥有哪些Sector呢?是MSAT,Master Sector Allocation Table。MSAT描述了哪些Sector是被SAT占用的。那谁描述MSAT存放在哪些Sector?好像无休止了!MSAT是存放在Header里的。这下摆脱溯源的烦恼了。但是Header大小是固定512字节的,因此能存的信息是有限制的。如果SAT占用的Sector很多很多,Header里都描述不下,怎么办?还是有办法的,扩展!当Header里的空间不够用时,就用Sector,在Header里有字段记录哪个Sector是MSAT扩展空间的第一个扇区,在MSAT专用的扇区里的最后4字节给出下一个MSAT专用的Sector,这样一个链表就现成了。因此一个MSAT扇区最多可以记录(512-4)/4=127个AST扇区。

通过MSAT就可以找出所有被SAT占用的Sector。这些SAT的Sector就描述了哪个几个Sector是属于一个Stream的以及Sector之间的顺序。这似乎又需要一个链表。对的。这次的链表结构是这样的:



把SAT看做一个数组,数组的元素就是扇区编号,扇区编号用4个字节来存储。比如SAT[i] = j,表示SAT数组的第i个元素是扇区编号j。如果把数组索引就当做扇区编号,SAT[i] = j,SAT[j] = k ... SAT[x] = -2,那么就有一串扇区编号了,i -> j -> k ...-> -2,扇区号-2表示串的结尾。这样,Stream就可以用这么一串扇区序列来描述的,关键是能有一个元数据描述这个Stream,并记录这个Stream的起始扇区号。知道了起始扇区号,就可以通过SAT找到所有其他Sector了。可见SAT也是一个链表结构。好像学数据结构的时候学过这种结构,具体叫啥忘记了。
那怎么存储Stream元数据呢?毫无疑问,是存放在Sector里。SAT就是存储了一些扇号串,看不出哪一串是用来描述Stream的元数据的。于是复合文档就有另一个概念了,目录(Directory)。Directory包含一个描述Stream和Storge的元数据的数据结构。如下图所示,目录里面有目录项,目录项也有编号,从0开始。
每个目录项就描述该项是Stream还是Storge,或者其他。如果是Stream,那么就记录起始扇区号是多少,如果是Storge,包含记录它有哪些Storge和Stream。一个Storge下可能有很多个Storge和Stream。复合文档是把这些子Stream和Storge组成一棵红黑树。这样Storge就可以只记录这颗红黑树的根节点就达到记录所有子Storge和Stream的目的。当然每个目录项得有字段里维护这么一颗红黑树。显然这种方式下,一个Stream或Storge只能在一棵红黑树里。为啥使用红黑树,有什么优点?慢慢思考中!
此外,复合文档还有其他一些概念,比如Short-Stream。Short-Stream一般存储在Root Storge这个目录项里。

2009年3月23日星期一

非常弱势

报喜鸟今天依然非常弱势,收盘才涨0.8%,大盘都涨了2%左右。3月19日的冲击涨停有人说是敢死队大单对倒,机构借机出货。敢死队干嘛要来对倒?试探?服装类股票美邦服饰,七匹狼都涨的很少。这周五美邦要公布年报了,能否启动,带领服装类股票反弹。预期报喜鸟的年报和一季报都是不错的,再耐心等等吧,马上到4月份了。
酒类股票也依然在底部震荡,还没起来的意思。不错。还有时间买入。

BloggerMode - syntaxhighlighter - Blogger Mode - Google Code

BloggerMode - syntaxhighlighter - Blogger Mode - Google Code: Blogger Mode
Blogger has a nasty habit of replacing all new lines with <br/> tags which makes it impossible to post code snippets.
To fix the situation version 1.5.1 introduces 'Blogger Mode' which can be enabled before a call to HighlightAll() by a call to BloggerMode() like in the example below:


dp.SyntaxHighlighter.BloggerMode();
dp.SyntaxHighlighter.HighlightAll('code');

Java.exe使用哪个JRE


/*
* Find path to JRE based on .exe's location or registry settings.
*/
jboolean
GetJREPath(char *path, jint pathsize)
{
char javadll[MAXPATHLEN];
struct stat s;

if (GetApplicationHome(path, pathsize)) { //If path is "c:\foo\bin\java", then application home is "c:\foo".
/* Is JRE co-located with the application? */
sprintf(javadll, "%s\\bin\\" JAVA_DLL, path);
if (stat(javadll, &s) == 0) {
goto found;
}

/* Does this app ship a private JRE in <apphome>\jre directory? */
sprintf(javadll, "%s\\jre\\bin\\" JAVA_DLL, path);
if (stat(javadll, &s) == 0) {
strcat(path, "\\jre");
goto found;
}
}

/* Look for a public JRE on this machine. Find path in registry. */
if (GetPublicJREHome(path, pathsize)) {
goto found;
}

fprintf(stderr, "Error: could not find " JAVA_DLL "\n");
return JNI_FALSE;

found:
if (_launcher_debug)
printf("JRE path is %s\n", path);
return JNI_TRUE;
}

Tips for software engineer: Using SyntaxHighlighter on BLOGGER

Tips for software engineer: Using SyntaxHighlighter on BLOGGER: "Using SyntaxHighlighter on BLOGGER "

SyntaxHighlighter is a free syntax highlighter written in JavaScript.

It can insert colored code snippets on a web page using client-side javascript only. It is ideal tool for users of BLOGGER because we do not have server side resource to parse and highlight the code. And we are lazy, we do not want to write a lot of CSS to just post a code snippet. :-).

However it takes a little twisting to make it work properly.

Below are the steps to setup:
1. Download and find a place to host the library files for SyntaxHighlighter. A free choice is, of course, Google Page Creator;
2. Login to BLOGGER, go to: 'Settings > Template > Edit HTML', make the following changes (credit goes to yehyeh's blog):

<link href='http://[YOUR HOST]/SyntaxHighlighter.css' rel='stylesheet' type='text/css'/>
<script src='http://[YOUR HOST]/shCore.js' type='text/javascript'/>

<script src='http://[YOUR HOST]/shBrushCpp.js' type='text/javascript'/>
<script src='http://[YOUR HOST]/shBrushCSharp.js' type='text/javascript'/>
<script src='http://[YOUR HOST]/shBrushCss.js' type='text/javascript'/>
<script src='http://[YOUR HOST]/shBrushJava.js' type='text/javascript'/>
<script src='http://[YOUR HOST]/shBrushJScript.js' type='text/javascript'/>
<script src='http://[YOUR HOST]/shBrushSql.js' type='text/javascript'/>
<script src='http://[YOUR HOST]/shBrushXml.js' type='text/javascript'/>

<script class='javascript'>
//<![CDATA[
function FindTagsByName(container, name, Tag)
{
var elements = document.getElementsByTagName(Tag);
for (var i = 0; i < elements.length; i++)
{
if (elements[i].getAttribute('name') == name)
{
container.push(elements[i]);
}
}
}

window.onload = function() {
var elements = [];
FindTagsByName(elements, 'code', 'pre');
FindTagsByName(elements, 'code', 'textarea');

for(var i=0; i < elements.length; i++) {
if(elements[i].nodeName.toUpperCase() == 'TEXTAREA') {
var childNode = elements[i].childNodes[0];
var newNode = document.createTextNode(childNode.nodeValue.replace(/<br\s*\/?>/gi,'\n'));
elements[i].replaceChild(newNode, childNode);

}
else if(elements[i].nodeName.toUpperCase() == 'PRE') {
brs = elements[i].getElementsByTagName('br');
for(var j = 0, brLength = brs.length; j < brLength; j++) {
var newNode = document.createTextNode('\n');
elements[i].replaceChild(newNode, brs[0]);
}
}
}
//clipboard does not work well, no line breaks
// dp.SyntaxHighlighter.ClipboardSwf =
//'http://[YOUR HOST]/clipboard.swf';
dp.SyntaxHighlighter.HighlightAll('code');
}
//]]>
</script>

3. Now you can post code snippet on BLOGGER using either 'pre' or 'textarea' tag.

Notice:
1. The solution above is found here: http://yehhou.blogspot.com/2007/06/blogger-dpsyntaxhighlighter.html. That blog was written in Chinese. I made some minor changes and posted here. The reason for the Javascript code to remove <br/> tags is because BLOGGER has a setting to automatically add <br/> where there is line break. It is very convenient feature for blog posters, but somehow syntax highlighter will display the <br/> tag in plain text;
2. Clipboard for the SyntaxHighlither does not work well here. It tends to give you the text without line breaks, so I commented out the Javascript that setup the clipboard function;
3. When posting HTML code, remember to replace < with &lt;, and replace > with &gt;;
Next:
Now you've got beautiful code in your blog, next step might be some nice charts for your blog. You will find a way to embed a chart with one line HTML code here: Embedding Chart in Web Pages Made Easy
And, here is a post to show you how to Embed Silverlight video on Blogger:Embed Silverlight Streaming in Blogger
Update 11/11/2008
There are a few questions and comments regarding script hosting. .NET Dev posted an interesting idea here:
http://urenjoy.blogspot.com/2008/10/publish-source-code-in-blogger.html

Basically, he setup the links directly to the trunk location of SyntaxHighlighter project.

打印Java.exe启动过程中的Debug信息

可以通过设置一个环境变量 _JAVA_LAUNCHER_DEBUG来实现打印Java.exe启动过程中的Debug信息。java.c有如下的代码:

if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) {
_launcher_debug = JNI_TRUE;
printf("----_JAVA_LAUNCHER_DEBUG----\n");
}


2009年3月20日星期五

2009年3月19日星期四

车型果盆

车型果盆,吃水果时可以玩一把,大小不一,叠在一起不占空间:

隐藏blogspot的navbar


#navbar-iframe {height:0px;visibility:hidden;display:none}

test

mail -> blogger