SDAV:Stardict for Android Version; Stardict的Android版实现

RT,既然是实现就说说怎么弄一个出来。

(说明:鉴于作者精神问题,基本胡扯)


零、无药可救了,为毛要从0开始,强迫症典型,要电。

不过话说优秀的程序员都是强迫症患者,这个我到有点自(我欣)慰。

首先看看linux下倒是有不少dict,但是android开源的真没有找到,找了半天懒得再去找了,不如自己弄一个算了。


一、老规矩:先说思路,思路正确其他都是体力活。

dict嘛,基本的功能无非就是一个dict+一个查询算法。linux下面开源词典多的是,既然不是做研究,而是为了应付工作,那么不用开源的反而显得自己有些2.

首选的是从sdcv来移植一个,why?如下:


哥从事开源软件(基本是索取)多年,用stardict多年,vim绑的都是sdcv(stardict console version)

如下脚本:

map ? <ESC>:!sdcv <cword><CR>

只要在要查询的单词上敲个?,就可以看到单词解释了。

一句话,感情啊,哥是一个重情谊的人。


二、怎么整?

既然有了目标从sdcv开搞,有几条路可以选

1 看懂sdcv,然后用java仿一个出来(哥不是QQ没有血轮眼,自己写还不累死我?我这么懒会自己写?)

2 jni

由于sdcv深度绑glib,tmd,不得不派生2个选择

 2.1 移植一个glib (可行,网上有介绍,也有开源项目,但是活跃度不高,估计也麻烦,想想头疼。另外,更重要的一点:把一个glib绑定到我的小dict中怎么感觉那么别扭呢?

唉,又tm是强迫症)

2.2 去glib,(这个当然可行,说白了,就是把glib的代码copy过来一起编译,就是一个蛋疼的重复劳动,但是难度最小,不打差的话,2天足够了。)

那么我就选择最2b的2.2吧,2.1等哥有空了在玩玩。


三、一个无聊的,2B的过程。

1 提取Makefile中编译命令,精简到无法再精简

g++ -DLOCALEDIR=\"/usr/local/share/locale\" -I. -I/usr/include/glib-2.0 -I/usr/lib/i386-linux-gnu/glib-2.0/include -Ilib -g3 -c -o sdcv.o sdcv.cpp

g++ -DLOCALEDIR=\"/usr/local/share/locale\" -I. -I/usr/include/glib-2.0 -I/usr/lib/i386-linux-gnu/glib-2.0/include -Ilib -g3 -c -o libwrapper.o libwrapper.cpp

。。。。。

g++ -g3 -o sdcv *.o lib/*.o -lz -lglib-2.0


得出可以运行的sdcv。

2 去掉: -lglib-2.0,这个glib库。重新编译sdcv,当然,一堆undefine。别怕,这些undefine就是你这2天要搬运的沙,IT民工嘛,不干干这些体力活,怎么体现打字速度这么大的优势?

找到glib代码中的相应函数,copy到相应undefine的代码中,rebuild,。。。。 不断重复这个过程,知道最后一个undefine也没有了。而且编译出来的sdcv运行ok。


ok,到这里应该已经过了1,2天了,别告诉哥,你半天就把那些undefine函数都替换了。


(注:以上2的方法,如其名,是一个非常非常2的方法,千万别tm把这个当成多好玩的事情!!,不得已的情况下,玩几次可以,你要的是理解代码运行,库依赖的关系即可。而不是享受这个唯一好处是锻炼手指肌肉的过程。这种事情一旦我们可以反抗就不要享受了)


3 到这里,你的无glib依赖的sdcv版本已经ok,next,我们要用jni来封装一下这些c++代码。

1、Android支持JNI,支持C++代码,但如果需要STL(这个是什么玩意?)需要:在jni目录建立Application.mk文件,输入: APP_STL := gnustl_static

$cat Application.mk

APP_STL := gnustl_static

$

2、你需要知道怎么用Andorid的JNI在Java和C代码之间传递数据,我们直接用hello-jni做模板套代码:omit

3、 sdcv的代码是C++的,而我们选择的hello-jni,是C code,所以需要在sdcv.cpp中把我们需要的接口 extern ”C" {}导出(其实就是demangle)

实际上,这里需要修改一下sdcv的输出,毕竟sdcv是输出到console的,我们需要接管他的printf(),把输出format 成我们的格式传递给JNI的接口函数。

哥为了偷懒就直接传string了。在sdcv的lib类加一个std::string result SetResult(),GetResult(),在所有printf()结果的地方直接调用SetResult(),在C++的接口函数GetResult()传递给JNI代码。具体就那么几行代码,omit。


四、debug,对,单独说debug。

纯android开发,eclipse的debug灰常好用

纯linux 代码的debug,自从有了cgdb,也灰常好用。

那么2者结合,就是JNI的debug了。(当然gdb显然没有cgdb好用,不过基本原理都一样)

                         [·一个窍门就是:先在android代码中下个break,然后在"工程目录"ndk-gdb,下好break,然后continue,再回到android层面操作即可。]


五、说那么多废话,其实没有什么有技术含量的东西。

弄这玩意,一个是我们的项目可能会用到一个dict,先自己预研一下,先把基调定高点,省得被那帮吃货用垃圾来忽悠。

另外一个是:为有需要的小朋友提供点思路,告诉大家至少有一条路是可行的。(大大们就见笑了)


六、//TODO:

补全:stardict的算法和词库的结构;整个代码量很小,3k(glib),5k(de-gilib)。

就是我用到的词库简单介绍一下。(其他应该都差不多)

首先一个词库有3个文件。

xxx.dz      压缩后的翻译data ;也可以不用压缩

xxx.ifo   词库信息,文本

xxx.idx   索引文件。


1, ifo文件中会标明当前词典有多少单词,作者是谁;翻译数据的格式(tmgx。。。:分别代表,有无音标,翻译,发音等。。)

2,idx文件,的格式为 一个string+U32+U32;比如 :fuck\0\offset\sizeJapanese\0\offset\size...............;看到了吧,就是单词+这个单词的偏移地址+单词翻译的长度。

(以上未必准确,大致就是 那么个意思);

所以,用编辑器可以打开看到所有的单词,比如vi xxx.idx,可以查找到“fuck”;

3 有了idx中的offset和size,我们当然可以很容易的在xxx.dz中read出size的数据了。这个size大小的数据就是未格式化的翻译data。这个data格式是在xxx.ifo中标明的,比如格式为tm,说明这个data是有音标+翻译: 

section 1:t

【f^K】

section 2:m

n 干

vt 干 日

。。。。

(当然,.dz文件都是zip格式的,读取的时候需要解压缩一下,这个libz之类的都会替你搞定)

4,说道这里你应该清楚了,所谓的字典文件,其实就是序列化的list!!!这个list的index和value分别保存到xxx.idx和xxx.dz文件中;list的其他信息如list.size保存到xxx.ifo文件中。

index格式是key+offset+size;

value格式是音标+发音+翻译(具体由ifo文件来确定)


5,so,搞清楚了字典文件格式,我们剩下了就是把他在format成list就哦了!

所谓的format,就是循环对预定义的数据结构DS,赋值。而已而已而已。。

只是

a 为了节省内存,我们需要用到分页读取,页面失效等算法(这些基本概念OS和DS相关课程和书籍都会提到omit)

b 为了加速,代码把format过的index memcpy到一个cache文件中,下次直接memcpy回来即可,不用再次一个一个format。

c 为了加速,查询的最近10个单词做了history。

d 默认目录/usr/share/stardict/dic/下面的所有词库都会被扫描,并使用。这个过程就是一个大的for(book b in allBooks)循环而已.

e 增加对字典的筛选,说白了就是(if name != xxx) continue;这个逻辑。


6 关键是一个字符串的相似度算法;现在网上也有一堆解释和说明。如果感兴趣可以研究研究,俺老了,懒得弄

通过这个算法实现一点小智能,比如你输入fuc 他能够根据字符串distance提供几个推荐(也就是相似的词)。


TODO:模糊查找相关代码没有看,估摸着不是循环就是用上面的算法算权值。


七、TODO ,优化

1 目前来看,是查询一个单词,重复一遍整个open read close;格式化,查询,关闭。完整过程。很多是可以合并的。至少在程序生命周期做一次就可以的。

2 速度:其实速度还可以,不耽误UE,

3 词库的智能匹配等。

4 for UE

5. 。。。。 

反正看着反馈改吧,现在不是流行微小改进频繁提交嘛。


chenee543216 AT gmail.com;有啥建议,意见欢迎交流。









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值