月度归档:2008年01月

要虐就一次虐个够

    话说我这次真的是受够了delphi。Delphi的unicode支持实在是太烂了,所有VCL都不支持unicode,要支持VCL只用用第三方的TNT(现在改名/收费了)。
    Delphi的一大好处就是控件多。unicode一下,那些第三方控件全部挂掉(就没几个控件是unicode的)。

发布“支持全文检索的大富翁浏览器”

下载地址:
支持全文索引的大富翁浏览器(Delphi盒子)

前言
    已经很久没有去大富翁了,后来想再去转转却发现连密码都已经忘记了。更惨的是密码找回的邮箱在去年被关闭了。这下密码是没办法用正常途径找回了。虽然有些可惜,但也算了吧相见不如怀念。
    前些天看到大富翁07年的离线数据库(非官方)发布了。在我早期玩delphi的时候大富翁的离线数据还是给了我很大的帮助的。我想从离线数据中收益的人应当不只我一个。曾有段时间离线浏览器层出不穷。当然离线数据最受欢迎的方式还是chm方式。只是随着离线数据的增大,要编译成单个CHM的难道增大。在04(03?)年后,chm版的离线数据就变成按年分的了。
    我想chm版的流行和良好的全文索引有很大的关系,目前的离线浏览器都是简单的使用数据库查询,一次无法对帖子内容等信息进行查询,大大限制了离线浏览器的用途。
    其实要增加全文索引的功能并不复杂,我也一直都有给离线浏览器加全文索引的想法(虽然我不用),只是Delphi的全文索引库一直没有出现。在去年(前年)的时候我看到了个lucene的Delphi版本,看似会是一个很有前途的东西,却在后来发现这东西居然需要.NET的支持。我对Delphi4.NET一直不待见。在我看来用Delphi对.NET进行封装完全是历史的倒退。接着说Delphi版本的lucene。虽然有4win32的计划,但似乎进展不大。JAVA和.NET都有垃圾收集机制,且JAVA和.NET的语言特性和delphi也有较大的差别,因此需要进行简单的移植难道并不会太小(c版的clucene也有不少问题,但至少算可用的)。
    虽然delphi自己整不了全文索引,但其实还是有不少办法来完成这个这个工作的。前些天我花了一晚上,用java的lucene给现有的离线浏览器加了个全文索引的功能。如果感兴趣就下了玩玩吧。

正文
    不知道现在是否还有人在用离线浏览器,不过即使没人用也没关系,这个程序更多的是演示如何使用混合语言进行开发。

    该版本是在“孟亚永"的离线浏览器基础上进行修改的,MYY的版本又是修改的左大侠的版本的。
    主要增加了全文索引功能(只支持问题)。
    加了全文索引的是主窗口上的快速搜索,将对所有帖子进行搜索(不包括回复)。
    本希望做成支持对回复也进行全文索引的,但这个数据库有些问题,离线浏览器部分不太好改。

  • 数据库的修改
    这个离线浏览器使用的数据库格式和newsmile的数据库有些不太一样,因此在使用前还得先动点手术。
    先执行
    Select ID, DateTime, UserFrom, Content, Parent into LettersReply from letters where Parent<>0
    生成回复表,然后在letters中删除回复信息
    delete from letters where Parent<>0
    再就是将letters的表名修改为lettersQ
    数据库的修改到这里就已经完成了,不过结果这些操作后数据库的个头大了不少,最好使用Access的压缩功能,压缩下。
    数据库修改后,还需要先建立索引,不然全文索引就无法工作,在bin目录下有个make_index.bat,直接运行这个脚本进行索引的创建。建立索引需要花点时间,我对2007的数据建立索引好像花了近10分钟。
  • JAVA部分
    由于全文索引用的是java的lucene,因此需要机器需要安装JDK。
    java部分全文索引的代码里面也带了。
    由于用到lucene,如果需要编译需要去下载个lucene(http://lucene.apache.org/java/docs/)。
  • 关于全文索引
    目前不少开发语言都有全文索引的支持。Delphi也有个,不过很怨念的是需要.NET的支持。
    虽然没有支持native的delphi全文索引库,但还是有些办法给native的delphi增加全文索引的支持的。
    比较容易做的方法有,将C++版本的全文索引库封成activex或DLL,不过我的C++不灵光,所以pass。
    python可以将类直接导出成activex,导出的方法简单。此外网上已经有人这么做了(doindex?)。但我测试pylucene的时候,中文索引通过不了。而且python导出的com需要启动一个com server,所以也pass。
    剩下最简单,最容易处理的方法就是将将全文索引部分写成一个单独的程序。在delphi里直接对这个程序进行调用,并通过获取控制台信息的方式,同索引服务器进行交互。目前采用的就是这个方式。
  • 关于JAVA的个头
    自从MS和SUN翻脸后,windows就不到jre了。要用户去安装一个1xM的JAVA虚拟机实在是一些让人为难。不过JRE还是可以精简到可以忍受的大小的。JRE1.5的虚拟机用7Zip压缩后大小为6xxK。库部分只对需要的部分打包,应当可以将JRE大小控制在2M内(我本来想精简下,不过今天是没时间了)。

使用JAVA在Linux进行串口开发的问题

    使用JAVA进行串口,实在是没啥难度,而且网上已经说的够多的了,因此我也不想多废话。不过其中有个问题实在是诡异(在Linux下)。
    虽然代码看上去没啥问题,但每当执行setSerialPortParams就抛出异常。
Detected: /dev/ttyM0 java.io.IOException: Not all params are supported by kernel
        at com.sun.comm.LinuxSerial.nativeSetSerialPortParams(Native Method)
    本以为是我 哪里搞错了,到网上一看才发现不少人遇到了和和同样的问题。问题的解决方案也是千奇百怪。有人说调用setSerialPortParams这个函数前要先sleep(10),有人说要先println。我加了print依旧失败,再往下看,有人说将setSerialPortParams这个函数放到try模块里就可以。加完try后再测试还真的好了。目前暂时只能将这个问题定义为“诡异”了。

Delphi的“BUG”

    其实不算是Delphi的BUG了,但真的是非常非常讨厌的一个特性。
    我本以为为初始化过的类就应当是nil。所以使用Assigned判断类变量是否初始化过。那知道我是否初始化过都能通过nil的检测。据说Delphi为了保证类函数的使用,会自动对这个类变量进行初始化。而当前类的指针就随便指向了一块内存空间。
    感觉这个问题实在是太讨厌了,大大增加了编码出错的概率。一个变量如果并不是需要在创建的时候初始化的你就无法通过判断是否为nil检测该变量是否初始化过,除非你在创建的时候就手动赋值为nil,但这点很容易被忽略掉。

PS:
    今天又和同学讨论了下这个问题。想来这个问题也是可以理解的,在C++中也存在类似的问题。看来我是被JAVA等高级语言给惯坏了。nil这个初始值虽然很简单,但确实很有用。