java diff 及wiki相关

diff的原理在于找两个字符串之间的最大相同子串(Longest Common Subsequence)以及编辑距离,比较有名的实现是UnixLinux上常用的diff(GNU Diff)。

实现

Java里Diff的实现我找了一下,主要是两个,java-diff 和bsmi上的Diff ,前者为LGPL,后一个为GPL。其实代码也都不多,都实现了LCS算法。前一个协议上对我们比较有利,而且文档、测试和例子多一些。
JavaDiff里主要有两个类,Diff和Difference类。前者是算法,后者是差异的表示类。下面讲一下例子:

Object[] a = new Object[] {         "a",         "b",         "c",         "d",         "e"     };     Object[] b = new Object[] {         "a",         "x",         "y",         "b",         "c",         "j",         "e",     };     Difference[] expected = new Difference[] {         new Difference(1-1,  1,  2),         new Difference(3,  3,  5,  5),     };     Diff diff = new Diff(a, b);     List diffOut = diff.diff();

差别有三处,用两个Difference对象表示。一个Difference对象表示替换,增加,删除。Difference的构造函数:

public Difference(int delStart, int delEnd, int addStart, int addEnd)

如果delEnd或者addEnd为-1的话,就代表没有删除或者增加行为。
回到例子,两个字符串之间的差别在于,目标字符串在第1-2行(从0算起)增加了x,y,第3行的d被第5行的j替换。Difference虽然只说明了行号和动作,但我们可以推算出来增加了什么,删除了什么,替换了什么。下面是另一个更长的例子,来自测试用例:

public void testStrings1()     {         Object[] a = new Object[] {             "a",             "b",             "c",             "e",             "h",             "j",             "l",             "m",             "n",             "p"         };         Object[] b = new Object[] {             "b",             "c",             "d",             "e",             "f",             "j",             "k",             "l",             "m",             "r",             "s",             "t"         };         Difference[] expected = new Difference[] {             new Difference(0,  0,  0-1),             new Difference(3-1,  2,  2),             new Difference(4,  4,  4,  4),             new Difference(6-1,  6,  6),             new Difference(8,  9,  911),         };         runDiff(a, b, expected);     }

上面比较的都是一个个字符串的差异,推广一下,把每一行文本当作一个字母,就可以得到文件的差异。在java-diff的etc下有一个FileDiff.java,是一个很好的参考。得到之间的差异之后,我们要把这个差异表示出来,这个需要包装一下,不过难度不大。

版本保存

还有一个wiki版本的保存问题。大的维基引擎如MediaWiki(就是维基百科那个,顺便说一下,维基百科的英文版终于可以访问了)没时间研究,就是 JSPWiki也没来得及看)(JSPWiki连数据库也不用,Web用自己写的框架,可读性可能比较不行)。只研究了trac的wiki实现。trac 的wiki实现很简单,就是把每一个版本都保存在数据库,毕竟都是文本的,还可以接受。每次比较的时候就从数据库里取两个版本出来做一个diff,具体实 现在PYTHON/site-packages/trac/wiki/web_ui.py(_render_diff函数)。trac提供两种形式的 diff结果,一个是tabular的表格形式,就是很直观的对比,还有一个是Unified的形式,也就是经常看见的diff结果。这是通过页面上 javascript读table里的文字转换成Unified格式的diff文本,虽然个人不推荐这种方式。wiki的文本修改又有一个特点,就是每一 行其实内容可能比较多,只改了几个字,这样就要对这一行的两个版本再做一个diff,然后把删除的文本用<del>标签,增加的文本用 <ins>标签展示出来。
最后提一下JSR-170,一个用来管理仓库内容(主要是大型CMS)的API,支持版本控制,存储多元化,很复杂,有两个商业实现和一个Apache JackRabbit的开源实现,这里 是一个参考资料。JSR170也是里面的例子也是把每一个版本都存储下来。

参考资料

通过电子路

    一直觉得电子路比较简单,加上练得比较多,自己一个人打饼有9成的把握。运气也好,抽到了直角转弯,3分钟就考好了。考官一直指点我开车,包括侧方停车时还直接帮我拉手刹、排空档。晚上接到教练的电话,问我下周一考不考大路,我晕。。。算了,下周一正好要期末考,还是下次吧,呵呵~~

计划有变

    这个学期一开始觉得自己的进度还可以,于是盘算着加快进度提前毕业。没想到今天得到消息,虽然是二手消息但还比较可靠,说是现在上面都不批准提前毕业了,提前完成学业可以,但是毕业证不能提前拿,要和其他人一起。这样基本就没有多少意义了。虽然这样,但事情还是按照计划做,至少,先把论文给发出来~~

Space被盾

    刚才想在上一篇blog里回复内容,发现失败,然后就像Google被盾一样,要隔几分钟才能访问博客。敏感内容无非就是50年代末叛逃到印度的那位五世先生。Space要删除评论之前要先浏览到评论的内容,于是我始终无法删除。。。找了代理,MSN却不让登录。。不过留言的也是无心的。这里小牢骚一下我们的GFW。

马赢就谢输

    4年前在宿舍关注对岸的大选,记得那个时候还没有自己的电脑,是在小猛男的电脑上看的。扁赢了,有同乡给我发很悲观的短信,我告诉她这是我们不能改变的历史,暂时和我们自身的关系也不太大,结果被扣上了不关心天下兴亡的帽子。对对岸的状态,我一直是持有独立的观点的,观点比较理想化,比较偏右。而最近西部边陲发生的几件事也开始改变我的一些看法,至少,绥靖肯定不是好办法。

    奥运年年初中国就碰到了一系列问题,大雪、通胀、三股分裂势力共同发难。马胜了200万票,至少先暂时解决了一个问题。马选前抛出的那些东西,都是为了拉拢选票摆出的姿态,上台以后该怎么干就怎么干,我还是比较看好他的,可以推动两岸经贸往来,开放三通。对家里的经济也很有好处,战争的威胁也暂时解除。

    不管怎么说,这是一个好消息。马有4年的任期,4年之内,我也会完成人生的一个大转变,start my career。到时候,面对可能的时局转变,不再只是指点江山。

    写点挺乱的,不知道自己在说什么了,呵呵~~

PSP和eInk

  记得以前初中高中的时候,宿舍的同学(好像是隔壁)偶尔会带游戏机在中午晚上玩一玩,最早是普通的GameBoy,后来进化到了GBA(GameBoy Advance)。那个时候有些眼馋,大家都是,常常围着一大帮人,五六个人轮流玩,大概一个中午也就玩个10分钟左右。虽然现在都有了电脑,但掌机的魅力依旧。以应用最广的PSP为例,除了有很多好玩的游戏,还可以看电影(嗯,eMule上的YYETS还提供专门的PSP,PDA,iPod格式的下载,人气比rmvb的还要高),看电子书,听音乐等等。另外任天堂的NDSL也不错,不错两个屏幕让我始终觉得很怪异,不习惯。最近常有人推荐我买PSP,其实就是我的两个老板,大老板和小老板,他们各有一个。这周周二坐校车回来正好被小老板逮个正着,坐在他旁边看他玩PSP,玩实况和赛车,一边推荐我买一个,说价格也不贵,1300就可以搞定。说的我还有些心动,煞有介事的查了查淘宝,上了很多网站看导购,大概总结出这么一个价位:PSP2000,仅主机大概1300多,全套装备比如SD卡等这些加上去大概要1700。再拖了几天,和一个朋友讨论了一下,觉得1700的大洋,不知道用得多不多,现在钱又不多,买了要赚回来还是挺不容易的,于是作罢。

  第二个东西是eInk,在程序员第三期潘家宇的文章里看到的推荐,翰林的v8 eInk阅读器,看上去感觉还很不错,支持各种格式,电子墨水,不像液晶屏那样看起来比较费眼睛,和普通的书籍一样靠外界的自然光来阅读,不翻页的话就不会耗电。这个东西的确是解决阅读电子书很好的解决方案,另外我的书多,带过来带过去很麻烦,计算机书籍普遍很厚,如果带上小黑的话再带一本书就很痛苦了,这个东西还是可以带来很多方便的。又是淘宝了一下,大概2700块钱,虽然比PSP还贵不少,但实在是很方便啊。但这个东西基本上属于小众市场,在网上购物并不是很放心,但实体店又嫌麻烦,不喜欢讨价还价,一阵挣扎后决定暂时搁置。

这个强,虽然火星了

Aoccdrnig to a rscheearch at Cmabrigde Uinervtisy, it deosn’t
mttaer in waht oredr the ltteers in a wrod are, the olny iprmoatnt tihng
is taht the frist and lsat ltteer be at the rghit pclae.The rset can be a
total mses and you can sitll raed it wouthit porbelm.

Tihs is bcuseae the huamn mnid deos not raed ervey lteter by istlef, but the
wrod as a wlohe.

我读到第二行才发现原来单词顺序都不对。在我看来,除了前两个字母以外,再加上单词字母的数量和上下文,人们基本就判断出来了,呵呵。

看来最好的代码阅读器还是IDE

这两天要研究下Acegi,给人做技术讲座,内容要求和Acegi有关。于是想找个代码阅读器来看代码。
第一个想到的就是SourceInsight,但考虑到SourceInsight还是收费软件,于是转向开源产品。搜了半天,找出一个Code Browser,没想到功能比Notepad++还差一些。于是无奈就用Eclispe看看代码。因为Acegi和Spring结合得很紧密,顺便把Spring IDE的帮助看了一下,第一次用了起来,觉得很好用啊。这么多年开发Spring应用居然都没好好用Spring IDE,真是惭愧。
Attach上Source的Eclispe+Spring IDE看起Acegi代码果然非常方便,按住Ctrl进行智能导航,还有引用查找等。怪不得一直找不到合适的开源代码查看器,原来IDE就已经这么好用了。

通过桩考

  一开始正手入库的时候没注意,居然左后视镜撞杆子了,晕,和模拟考的时候一样的毛病。被教练狠狠的骂了一通后,第二次小心翼翼的过了。紧张死了,虽然觉得没什么难的。唉,接下来还要学电子路考和大路考,两个星期的桩考就把我折腾了好一回,还有两项。。。看来学开车是挺累的。

早起

    上个礼拜因为开车,天天早上7点多一点就起床,骑车去4公里外的驾校培训。于是也就慢慢适应了早起的日子,感觉很不错。周末估计再多睡一个小时,要好好坚持下去。